trouble in query - sql

hey every one i have this record
id date hours groupkey
1 1-12-2016 1 NULL
2 2-12-2016 2 NULL
3 3-12-2016 1 3
4 4-12-2016 1 3
5 5-12-2016 1 3
and i want this
id startdate enddate hours
1 1-12-2016 1-12-2016 1
2 2-12-2016 2-12-2016 2
3 3-12-2016 5-12-2016 3
i am using this query
SELECT Max(Isnull(groupkey, id)) AS id,
Min(date) AS startdate,
Max(date) AS enddate,
Sum(timeoffhours) AS hours,
CASE
WHEN Min(groupkey) IS NULL THEN 'No'
ELSE 'Yes'
END Status
FROM table
WHERE employeekey = 20
AND date >= '1/1/2016'
AND date <= '12/31/2016'
GROUP BY groupkey
but it is making one row for null group key please help me

You should GROUP BY Isnull(groupkey, id)) to solve your issue here. You're still grouping on the regular groupkey.

Try in dynamic table
SELECT
id, startdate, enddate, hours,
CASE WHEN mingroup IS NULL THEN 'No' ELSE 'YES' END AS status
FROM
(SELECT
MAX(ISNULL(groupkey, id)) AS id,
MIN(date) AS startdate,
MAX(date) AS enddate,
SUM(timeoffhours) AS hours,
MIN(groupkey) AS mingroup
FROM
table
WHERE
employeekey = 20
AND date >= '1/1/2016'
AND date <= '12/31/2016'
GROUP BY
groupkey)

BEGIN TRAN
CREATE TABLE #Temp (id INT IDENTITY(1,1) , _date DATE ,_hours INT , groupkey INT)
CREATE TABLE #OutPutTemp (_id INT , _Startdate DATE ,_EndDate DATE, _Hours INT)
INSERT INTO #Temp (_date ,_hours , groupkey )
SELECT '1-12-2016' ,1,NULL UNION ALL
SELECT '2-12-2016' ,2,NULL UNION ALL
SELECT '3-12-2016' ,1,3 UNION ALL
SELECT '4-12-2016' ,1,3 UNION ALL
SELECT '5-12-2016' ,1,3
INSERT INTO #OutPutTemp(_id , _Startdate ,_EndDate,_Hours)
SELECT id , _date , _date , _hours
FROM #Temp
WHERE ISNULL(groupkey,0) = 0
INSERT INTO #OutPutTemp(_id)
SELECT groupkey
FROM #Temp
WHERE ISNULL(groupkey,0) <> 0
GROUP BY groupkey
UPDATE #OutPutTemp SET _Startdate = Startdate
FROM
(
SELECT MIN(_date) Startdate ,groupkey
FROM #Temp
WHERE ISNULL(groupkey,0) <> 0
GROUP BY groupkey
)A
WHERE _id = groupkey
UPDATE #OutPutTemp SET _EndDate = EndDate
FROM
(
SELECT MAX(_date) EndDate ,groupkey
FROM #Temp
WHERE ISNULL(groupkey,0) <> 0
GROUP BY groupkey
)B
WHERE _id = groupkey
UPDATE #OutPutTemp SET _hours = tothours
FROM
(
SELECT SUM(_hours) tothours ,groupkey
FROM #Temp
WHERE ISNULL(groupkey,0) <> 0
GROUP BY groupkey
)C
WHERE _id = groupkey
SELECT * FROM #OutPutTemp
ROLLBACK TRAN

Related

SQL case statement closest to current date

Need help create a case statement to find the closest date from date table. My data: https://imgur.com/hkBu4SA
I basically want to set:
Y flag if it's closest to today's date from a.FROM_EFFDT and is not null.
F if to_effdate is null
else N
WHEN a.FROM_EFFDT < GETDATE() AND (to_effdate) IS NOT NULL THEN 'Y'
WHEN to_effdate IS NULL THEN 'F'
ELSE 'N'
You can use window functions:
(case when row_number() over (order by abs(datediff(day, getdate(), to_effdate)) = 1
then 'Y'
when to_effdate is null then 'F'
else 'N'
end)
You may be able to accomplish it with something like this. Though this isn't bulletproof, you could get duplicates if the closest date is tied.
create table Dates (from_effdt datetime, to_effdt datetime, flag varchar(1))
insert Dates (from_effdt, to_effdt, flag)
values
('2019-03-16', null, '') ,
('2018-06-14', '2019-03-16', '') ,
('2018-05-14', '2018-06-14', '') ,
('2018-01-01', '2018-05-14', '')
select * from Dates
UPDATE Dates
SET flag =
CASE
WHEN from_effdt = (
select top 1 from_effdt
from Dates
order by ABS ( DATEDIFF(day, from_effdt, getdate()) )
)
THEN 'Y'
ELSE
'N'
END
*update, not sure why I created it as an update. This select should do.
SELECT from_effdt, to_effdt,
CASE
WHEN from_effdt = (
select top 1 from_effdt
from Dates
order by ABS ( DATEDIFF(day, from_effdt, getdate()) )
)
THEN 'Y'
ELSE
'N'
END [numberOfDaysAway]
FROM Dates
You can simply do this:
CASE
WHEN from_effdt = (
select from_effdt
from Dates
where abs(datediff(second, from_effdt, getdate()))
= (select min(
abs(datediff(second, from_effdt, getdate()))
)
from Dates)
)
THEN 'Y'
ELSE
'N'
END
ROW_NUMBER() Over (Partition by id order by to_effdt desc)
,id
,from_effdt
,to_effdt
, CASE WHEN (ROW_NUMBER() Over (Partition by id order by to_effdt desc) = 1) THEN ('Y')
WHEN (to_effdt IS NULL) THEN ('F') ELSE ('N') End as flag
from a

ADJUST/EDIT SQL QUERY ASSISTANCE

I have the below query which calculates from the first requested date to first completed date how much time elapsed.
However in the example below there is a requested date of 2017-02-02 (backdated) which was created on the 2017-02-06.
I want to edit the query to select the requested date and calculate how much time elapsed until completed from the FIRST CREATED DATE
So right now it returns 1 when it should be 0
Reasoning, because first created date is 2017-02-03 and it was requested and completed on the same day 2017-02-03
Any help is appreciated greatly!
CREATE TABLE #temp
(Identifier VARCHAR(40) NOT NULL,
Created_Date DATETIME NOT NULL,
Requested_Date DATETIME NOT NULL,
Completed_Date DATETIME NULL,
SN_Type VARCHAR(20) NOT NULL,
SN_Status VARCHAR(20) NOT NULL
);
INSERT INTO #temp
VALUES
('11111',
'20170203',
'20170203',
'20170203',
'Re-Activattion',
'COMP'
);
INSERT INTO #temp
VALUES
('11111',
'20170206',
'20170202',
NULL,
'Re-Activattion',
'N-CO'
);
SELECT *
FROM #temp;
-- calculate/identify Order start and Order End records
WITH cte
AS (
-- 1st Order start record i.e. earliest record in the table for a given "Identifier"
SELECT Identifier,
MIN(Created_Date) AS Created_Date,
CONVERT(VARCHAR(30), 'Created') AS RecordType,
1 AS OrderNumber
FROM #temp
GROUP BY Identifier
UNION ALL
-- All records with "COMP" status are treated as order completed events. Add 2 weeks to the completed date to create a "dummy" Order End Date
SELECT Identifier,
DATEADD(WEEK, 2, Created_Date) AS Created_Date,
'Completed' AS RecordType,
ROW_NUMBER() OVER(PARTITION BY Identifier ORDER BY Created_Date) AS OrderNumber
FROM #temp
WHERE SN_STATUS = 'COMP'
UNION ALL
-- Set the start period of the next order to be right after (3 ms) the previous Order End Date
SELECT Identifier,
DATEADD(ms, 3, DATEADD(WEEK, 2, Created_Date)) AS Created_Date,
'Created' AS RecordType,
ROW_NUMBER() OVER(PARTITION BY Identifier ORDER BY Created_Date) + 1 AS OrderNumber
FROM #temp
WHERE SN_STATUS = 'COMP'),
-- Combine Start / End records into one record
OrderGroups
AS (
SELECT Identifier,
OrderNumber,
MIN(Created_Date) AS OrderRangeStartDate,
MAX(Created_Date) AS OrderRangeEndDate
FROM cte
GROUP BY Identifier,
OrderNumber)
SELECT a.Identifier,
a.OrderNumber,
OrderRangeStartDate,
OrderRangeEndDate,
CASE
WHEN SUM(CASE
WHEN SN_STATUS = 'COMP'
AND SN_TYPE = 'Re-Activattion'
THEN 1
ELSE 0
END) > 0
THEN STR(DATEDIFF(day, MIN(CASE
WHEN SN_TYPE = 'Re-Activattion'
THEN Requested_Date
ELSE NULL
END), MIN(CASE
WHEN(SN_TYPE = 'Re-Activattion'
AND SN_STATUS = 'COMP')
THEN Completed_Date
ELSE NULL
END)))
WHEN SUM(CASE
WHEN SN_TYPE = 'Re-Activattion'
THEN 1
ELSE 0
END) > 0
THEN 'NOT COMP'
ELSE 'NO RE-ACT'
END AS RE_ACT_COMPLETION_TIME,
SUM(CASE
WHEN SN_STATUS = 'N-CO'
THEN 1
ELSE 0
END) AS [RE-AN NCO #]
FROM OrderGroups AS a
INNER JOIN #Temp AS b ON a.Identifier = b.Identifier
AND a.OrderRangeStartDate <= b.Created_Date
AND b.Created_Date <= a.OrderRangeEndDate
GROUP BY a.Identifier,
a.OrderNumber,
OrderRangeStartDate,
OrderRangeEndDate;
I want to edit the query to select the requested date and calculate
how much time elapsed until completed from the FIRST CREATED DATE
Change this:
,MIN(case
when SN_TYPE = 'Re-Activattion'
then Requested_Date
else null
end
To this:
,MIN(case
when SN_TYPE = 'Re-Activattion'
then Created_Date
else null
end

Iterate value dynamically

I'm using the below query to calculate a budget value dynamically means iterating upto selected date value.
SUM(case when Name = 'Budget' then Value + ((Value/#TotaldaysinMonth) *
#DaysPastinMonth) end) as [Budget]
Here variable #DaysPastinMonth should be dynamic. Means if I select a date as 03/31/2017. Then the query should run upto the previous month value. Another example is if I select August, then I need to run query from Jan-Aug.
For Jan
SUM(case when Name = 'Budget' then Value + ((Value/#TotaldaysinMonth) *
#DaysPastinJanMonth) end) as [Budget]
For Feb
SUM(case when Name = 'Budget' then Value + ((Value/#TotaldaysinMonth) *
#DaysPastinFebMonth) end) as [Budget]
For Mar
SUM(case when Name = 'Budget' then Value + ((Value/#TotaldaysinMonth) *
#DaysPastinMarMonth) end) as [Budget]
Also I have created variables for all the 12 months which holds DaysPastinMonth.
Can anyone suggest how this can be achieved using case statement.
You are thinking about this in loop when you could do it with set based operations.
----------------------------------------------------------
--Create a table of dates for testing
----------------------------------------------------------
if object_id('tempdb..#dates') is not null
drop table #dates
create table #dates(d date
,RN bigint)
declare #sdate datetime='2017-01-01 00:00'
declare #edate datetime='2017-7-31 00:00'
insert into #dates
select
DATEADD(d,number,#sdate)
,row_number() over (order by (select null)) as RN
from
master..spt_values
where
type='P'
and number<=datediff(d,#sdate,#edate)
declare #numOfDays int = (select count(*) from #dates)
----------------------------------------------------------
--Populate Test Data
----------------------------------------------------------
if object_id('tempdb..#testTable') is not null
drop table #testTable
create table #testTable([Name] varchar(64),
[Value] decimal (16,4),
DT datetime)
insert into #testTable ([Name],[Value],DT)
select
'Budget'
,r.randomNumber
,d.d
from
#dates d
inner join
(SELECT TOP (select #numOfDays)
randomNumber,
row_number() over (order by (select null)) as RN
FROM (
SELECT CAST(ABS(CAST(NEWID() AS binary(6)) %100000) + RAND() AS DECIMAL (16,4)) + 1 randomNumber
FROM sysobjects) sample
GROUP BY randomNumber
ORDER BY randomNumber DESC) r on r.RN = d.RN
union all
select
'Not The Budget'
,r.randomNumber
,d.d
from
#dates d
inner join
(SELECT TOP (select #numOfDays)
randomNumber,
row_number() over (order by (select null)) as RN
FROM (
SELECT CAST(ABS(CAST(NEWID() AS binary(6)) %100000) + RAND() AS DECIMAL (16,4)) + 1 randomNumber
FROM sysobjects) sample
GROUP BY randomNumber
ORDER BY randomNumber DESC) r on r.RN = d.RN
----------------------------------------------------------
--Instead of making your variables "dynamic" which
--would likely consist of some loop, just pass in the
--month you care about and let SQL do the work
----------------------------------------------------------
declare #month datetime = '2016-03-31'
select
DT
,[Value]
,[Name]
,sum(case when [Name] = 'Budget'
then [Value] +
(([Value] / (DATEDIFF(day,DATEADD(month, DATEDIFF(month, 0, #month), 0),#month)))
*
(DATEDIFF(DAY,DATEADD(MONTH, DATEDIFF(MONTH, 0, #month)-1, 0),DATEADD(MONTH, DATEDIFF(MONTH, -1, #month)-1, -1)))) end) as Budget
from
#testTable
where
DT >= DATEADD(yy, DATEDIFF(yy, 0, #month), 0) --this is Jan 1 of the year associated with your vairable
group by
DT
,[Name]
,[Value]

Insert a series of dates into sql startdate and enddate inputs

I have this table:
**ID StartDate EndDate**
1 01/01/2012 03/01/2012
2 28/09/2013 02/10/2013
3 12/06/2011 15/06/2011
And I need to have this table:
Date
**ID Date**
1 01/01/2012
1 02/01/2012
1 03/01/2012
2 28/09/2013
2 29/09/2013
2 30/09/2013
2 01/10/2013
2 02/10/2013
3 12/06/2011
3 13/06/2011
3 14/06/2011
3 15/06/2011
I Have Next Sql Code That Retarn The Dates Between The StartDate & The EndDate + StartDate +EndDate :
declare #Start datetime
declare #end datetime
declare #request int
set #Start = '2014-09-28 06:53:04.560'
set #end = '2014-09-29 11:53:04.560'
set #request = 1
;with Dates as (
select #request as reqId,#Start as reqDate
union all
select reqId+1,DATEADD(hh,1,reqDate) from Dates
where reqDate < #end
)
select * from Dates
How Can I Get This Result For A Bulk Of StartDate-EndDate Input?
You can do this by using your source date table as below
declare #request int
set #request = 1
;with Dates as (
SELECT #request as reqId,StartDate as reqDate, EndDate
FROM yourDateTable
UNION ALL
SELECT reqId+1,DATEADD(DAY,1,reqDate),Dates.EndDate
FROM Dates
WHERE DATEADD(DAY,1,reqDate) < EndDate
)
SELECT *
FROM Dates
Use recursive query
CREATE TABLE #ranges
(
Id INT ,
startDate DATE ,
ENdDate DATE
)
INSERT #ranges
( Id, startDate, ENdDate )
VALUES ( 1, '2014-5-2', '2014-5-5' ),
( 2, '2014-8-29', '2014-9-3' ),
( 3, '2014-10-2', '2014-10-8' );
WITH
cte
AS ( SELECT *
FROM #ranges
UNION ALL
SELECT id ,
DATEADD(DAY, 1, startDate) ,
EndDate
FROM cte
WHERE DATEADD(DAY, 1, startDate) <= EndDate
)
SELECT Id ,
startDate Date
FROM cte
ORDER BY Id ,
startDate
DROP TABLE #ranges
DECLARE #MyPeriod TABLE (
ID INT NOT NULL IDENTITY PRIMARY KEY
,StartDate date
,EndDate date
);
INSERT INTO #MyPeriod (StartDate, EndDate)
VALUES ('20120101','20120103')
,('20130928','20131002')
,('20110612','20110615');
SELECT *
FROM #MyPeriod
declare #Start date
declare #end date
set #Start = '2000-01-01'
set #end = '2020-01-01'
;with Dates as (
select #Start as Date
union all
select DATEADD(day,1,Date) from Dates
where Date < #end
)
select MyPeriod.ID, Dates.Date
from Dates
INNER JOIN #MyPeriod MyPeriod
ON Dates.Date BETWEEN MyPeriod.StartDate AND MyPeriod.EndDate
ORDER BY Dates.Date
OPTION(MAXRECURSION 0);
Try this!
CREATE TABLE #TempTable(
ID int,
[Date] date
)
DECLARE #ROWCOUNT INT,#ID INT
DECLARE #Date1 DATE, #Date2 DATE
SET #ROWCOUNT = 1
SET #ID=''
SET #Date1=''
SET #Date1=''
WHILE (#ROWCOUNT <= (SELECT COUNT(*) FROM your_table_name))
BEGIN
SET #ID=(SELECT id FROM your_table_name WHERE ID=#ROWCOUNT)
SET #Date1=(SELECT StartDate FROM your_table_name WHERE ID=#ROWCOUNT)
SET #Date2=(SELECT EndDate FROM your_table_name WHERE ID=#ROWCOUNT)
INSERT INTO #TempTable
SELECT #ID, DATEADD(DAY,number,#Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY,number, #Date1) <= #Date2
SET #ROWCOUNT = #ROWCOUNT + 1
END
SELECT * FROM #TempTable
DROP TABLE #TempTable

SQL cross tab pivot query

I have a table as below.
CaseID StatusID StageID CaseRegisterTime City
1 1 5 datetime XYZ
2 1 5 datetime ABC
Now I want its Citywise count and only for only specific dates, and also in condition for statusid = 1 and stageid = 5.
Cities CurrentDate-1 CurrentDate-2 January2012-CurrentDate-3
XYZ 5 51 5008
JUS 0 0 125
ABC 1 0 48
I want my header to group cases for CaseRegisterTime as shown above.
Please help.
Use case when to convert your dates of interest to 'CurrentDate-1' and 'CurrentDate-2', and then pivot the results, using this strings as the new columns.
Alternatively, you can do something like this:
select City, sum(Date1) as Date1, sum(Date2) as Date2
from(
select City,
case when CaseRegisterTime='2012-01-01' then 1 else 0 end as Date1,
case when CaseRegisterTime='2012-15-01' then 1 else 0 end as Date2
from sample
) as T
group by City
you'd also have to filter out the registers which doesn't have the desired date.
Here's one of many ways to do it in SQL Server 2008 (using the Date datatype):
select distinct a.City as Cities
, (select count(*)
from MyTable
where CaseRegisterTime >= cast(getdate() - 1 as date)
and CaseRegisterTime < cast(getdate() - 0 as date)
and StatusID = a.StatusID
and StageID = a.StageID
and City = a.City
) as [CurrentDate-1]
, (select count(*)
from MyTable
where CaseRegisterTime >= cast(getdate() - 2 as date)
and CaseRegisterTime < cast(getdate() - 1 as date)
and StatusID = a.StatusID
and StageID = a.StageID
and City = a.City
) as [CurrentDate-2]
, (select count(*)
from MyTable
where CaseRegisterTime >= cast('20120101' as date)
and CaseRegisterTime < cast(getdate() - 2 as date)
and StatusID = a.StatusID
and StageID = a.StageID
and City = a.City
) as [January2012-CurrentDate-3]
from MyTable a
where a.StatusID = 1
and a.StageID = 5
Update
The case and sum method #JotaBe uses is about twice as fast on my box (with many less scans and reads), so here's what that could look like:
select a.City as Cities
, sum(a.[CurrentDate-1]) as [CurrentDate-1]
, sum(a.[CurrentDate-2]) as [CurrentDate-2]
, sum(a.[January2012-CurrentDate-3]) as [January2012-CurrentDate-3]
from (
select City
, case when CaseRegisterTime >= cast(getdate() - 1 as date)
and CaseRegisterTime < cast(getdate() - 0 as date)
then 1 else 0 end [CurrentDate-1]
, case when CaseRegisterTime >= cast(getdate() - 2 as date)
and CaseRegisterTime < cast(getdate() - 1 as date)
then 1 else 0 end [CurrentDate-2]
, case when CaseRegisterTime >= cast('20120101' as date)
and CaseRegisterTime < cast(getdate() - 2 as date)
then 1 else 0 end [January2012-CurrentDate-3]
from MyTable
where StatusID = 1
and StageID = 5
) as a
group by a.City
Something like this will do:
begin tran;
go
create table #t1(
ID int identity,
City varchar,
RegisterDate datetime
);
declare #firstDate datetime, #secondDate datetime;
set #firstDate = '2012-1-1';
set #secondDate = '2012-1-2';
insert into #t1 values
('A', #firstDate),
('A', #firstDate),
('B', #firstDate),
('B', #firstDate),
('B', #firstDate),
('A', #secondDate),
('A', #secondDate),
('A', #secondDate),
('B', #secondDate),
('B', #secondDate);
select * from #t1;
select pvt.*
from(
select ID, City, RegisterDate
from #t1
) a
pivot(
count(a.ID)
for a.RegisterDate in ([2012-1-1], [2012-1-2])
) as pvt;
drop table #t1;
go
rollback tran;