I have a sample query as shown below,
SELECT SUM(Test) AS TotalLastMonth
FROM Table
WHERE date >=DATEADD(MONTH, -1, getdate())
GROUP BY InvoiceNo
Result:
22
12
34
21
16
10
18
I am trying to retrieve multiple months data into multiple columns.Sample output
TotalLastMonth TotalLast6Months TotalLast12Months
10 22 97
12 24 57
15 30 63
21 42 78
25 50 75
Conditional aggregation would work...
select
TotalLastMonth = sum(case when date >= dateadd(month,-1,getdate()) then Test end)
,TotalLast6Months = sum(case when date >= dateadd(month,-6,getdate()) then Test end)
,TotalLast6Months = sum(case when date >= dateadd(month,-12,getdate()) then Test end)
If you want whole months excluding this month, then use your DATEADD logic to get the first of the month, and last of the month.
select
--total last month, not including this month
TotalLastMonth = sum(case when date >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-1, 0) and date < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) then Test end)
--total last 6 months not including this month
,TotalLast6Months = sum(case when date >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-6, 0) and date < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) then Test end)
--total last 12 months not including this month
,TotalLast6Months = sum(case when date >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-12, 0) and date < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) then Test end)
Related
I need small help, I have to configure one report where client want only 15 days data.in following way
if day of month is less than or equal to 15 then range of date would be 1 to 15 if date exceed 15 then range of date would be 16 to 30 or 31
select * from TABLE_NAME
where DATEPART(day, DATE_COLUMN) between
(case when datepart(day, getdate()) <= 15 then 1 else 16 end) and
(case when datepart(day, getdate()) <= 15 then 15 else 31 end)
You could also try
SELECT * FROM <table> WHERE [date] between
case when DATEPART(DAY, GETDATE()) <=15 then DATEADD(month, DATEDIFF(month, 0, getdate()), 0) else DATEADD(month, DATEDIFF(month, 0, getdate()), 15) end
and
case when DATEPART(DAY, GETDATE()) <=15 then DATEADD(month, DATEDIFF(month, 0, getdate()), 15) else DATEADD(MONTH,1+DATEDIFF(MONTH,0,GETDATE()),-1) end
This query may give you the proper result
SELECT * FROM TableName
WHERE 1 = (
CASE WHEN DAY(GETDATE()) <= 15 THEN
CASE WHEN (DateField BETWEEN CONVERT(DATETIME,CONVERT(VARCHAR,MONTH(DateField)) + '-' + '1-' + CONVERT(VARCHAR,YEAR(DateField)))
AND CONVERT(DATETIME,CONVERT(VARCHAR,MONTH(DateField)) + '-' + '15-' + CONVERT(VARCHAR,YEAR(DateField))))
THEN 1 ELSE 0 END
ELSE
CASE WHEN(DateField BETWEEN CONVERT(DATETIME,CONVERT(VARCHAR,MONTH(DateField)) + '-' + '16-' + CONVERT(VARCHAR,YEAR(DateField)))
AND CONVERT(DATETIME,CONVERT(VARCHAR,MONTH(DateField)) + '-' + CONVERT(VARCHAR,DAY(EOMONTH(DateField))) + '-' + CONVERT(VARCHAR,YEAR(DateField))))
THEN 1 ELSE 0 END
END)
I try to count the no. of bills received between 30,60 and above 90 days.
Here is my T-SQL query:
SELECT
costcentreid,
'Current' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) < 30
THEN COUNT(PVNo)
END,
'30_days' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 30 AND 60
THEN COUNT(PVNo)
END,
'60_days' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 60 AND 90
THEN COUNT(PVNo)
END,
'90_plus' = CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) > 90
THEN COUNT(PVNo)
END
FROM
SPRGMMS..PVRegister
GROUP BY
CostCentreId
When I run this, I get an error:
Msg 8120, Level 16, State 1, Line 2
Column '[DB]..PVRegister.BillDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Kindly help
You need the aggregation outside
SELECT
costcentreid,
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) < 30
THEN PVNo
END) as 'Current',
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 30 AND 60
THEN PVNo
END) as '30_days',
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) BETWEEN 60 AND 90
THEN PVNo
END) as '60_days',
COUNT(CASE
WHEN DATEDIFF(DAY, BillDate, Getdate()) > 90
THEN PVNo
END) as '90_plus'
FROM
SPRGMMS..PVRegister
GROUP BY CostCentreId
SELECT
costcentreid,
SUM(CASE WHEN d = 1 THEN 1 ELSE 0 END) AS '30_days'
SUM(CASE WHEN d = 2 THEN 1 ELSE 0 END) AS '60_days',
SUM(CASE WHEN d = 3 THEN 1 ELSE 0 END) AS '90_days',
FROM (
SELECT PVNo, costcentreid, DATEDIFF(DAY, BillDate, Getdate())) / 30 AS d FROM SPRGMMS..PVRegister
) T
WHERE d <= 3
GROUP BY costcentreid
I have a table with the following data:
ItemId PendingTime
1 2016-11-23 15:57:56.000
2 2016-07-09 17:33:09.000
3 2015-11-27 18:34:03.000
and so on..
I would like to know sum of items pending since last 30 mins, last 1 hr, last 1 week, last 1 month and over an year. I came up with the following query:
SELECT
SUM(CASE
WHEN datediff(MINUTE, PENDING_TIME,GETDATE()) <= 30
THEN 1 ELSE 0
END) AS '30 Min',
Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 30 AND (datediff(MINUTE,PENDING_TIME, GETDATE())) <= 60 then 1 Else 0 End) as 'Over 30 Min',
Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 60 AND (datediff(HOUR,PENDING_TIME, GETDATE())) <= 24 then 1 Else 0 End) as 'Over 1 Hr',
Sum(case when (datediff(DAY,PENDING_TIME, GETDATE())) > 1 AND (datediff(DAY,PENDING_TIME, GETDATE())) < 30 then 1 Else 0 End) as '1 month',
Sum(case when datediff(DAY,PENDING_TIME, GETDATE()) >= 30 then 1 Else 0 End) as 'More than month'
from ItemsTable where datepart(yyyy,PENDING_TIME) = DATEPART(yyyy,GETDATE())
This returns data as:
30 Min Over 30 Min Over 1 Hr 1 month More than month
----------- ----------- ----------- ----------- ---------------
100 350 NULL NULL NULL
I would like the results in 2 column format as:
30 Min ------ 45
Over 30 ------ 100
Over 1 hr ------ null
Over 1 month ------ null
I am aware of the pivot function, however the columns I have selected aren't really in the table I am selecting from, rather they are created as result of aggregate function.
How do I get this in 2 column and multiple rows format.
Thanks for reading through.
You can create a derived column which classifies the waits into different types, then group by that column:
With waitCodes As (
Select Case
When DateDiff(Minute, PENDING_TIME, GetDate()) <= 30 Then '30 Min'
When DateDiff(Minute, PENDING_TIME, GetDate()) <= 60 Then 'Over 30'
When DateDiff(Minute, PENDING_TIME, GetDate()) <= 1440 Then 'Over 1 hr'
When DateDiff(Minute, PENDING_TIME, GetDate()) <= 43200 Then '1 month'
Else 'More than a month' End As [WaitTime]
From ItemsTable
Where DatePart(yyyy, PENDING_TIME) = DatePart(yyyy,GetDate()))
Select [WaitTime], Count(*) As n
From waitCodes
Group By [WaitTime];
In addition, I strongly recommend you change the Where clause in your query so that it doesn't apply a function to the PENDING_TIME column. There are multiple benefits of this.
...
Where PENDING_TIME >= Convert(date, Convert(char(4), DatePart(yyyy, GetDate()))+'-01-01 00:00:00.000', 121)
And PENDING_TIME < Convert(date, Convert(char(4), DatePart(yyyy, GetDate())+1)+'-01-01 00:00:00.000', 121)
....
you can use cross apply statement per orignal sql like this
SELECT c.* FROM
(
SELECT
SUM(CASE
WHEN datediff(MINUTE, PENDING_TIME,GETDATE()) <= 30
THEN 1 ELSE 0
END) AS '30 Min',
Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 30 AND (datediff(MINUTE,PENDING_TIME, GETDATE())) <= 60 then 1 Else 0 End) as 'Over 30 Min',
Sum(case when (datediff(MINUTE,PENDING_TIME, GETDATE())) > 60 AND (datediff(HOUR,PENDING_TIME, GETDATE())) <= 24 then 1 Else 0 End) as 'Over 1 Hr',
Sum(case when (datediff(DAY,PENDING_TIME, GETDATE())) > 1 AND (datediff(DAY,PENDING_TIME, GETDATE())) < 30 then 1 Else 0 End) as '1 month',
Sum(case when datediff(DAY,PENDING_TIME, GETDATE()) >= 30 then 1 Else 0 End) as 'More than month'
from ItemsTable where datepart(yyyy,PENDING_TIME) = DATEPART(yyyy,GETDATE())
)
CROSS APPLY(VALUES('30 MIN',a),('Over 30',b),('Over 1 hr',c),('Over 1 month',d),('More than month',e)) c(title,[value])
result:
title value
--------------- -----------
30 MIN 100
Over 30 350
Over 1 hr NULL
Over 1 month NULL
More than month NULL
I have been trying to generate a report based on different date ranges. But the query that I have written is combining all results into one. Expecting to get 4 results for 4 date ranges.
PS: I am a beginner. Any help would be appreciated.
select
sum(case when IsBlank = 1 then 1 else 0 end) as BlankChats,
sum(case when LeadID > 0 then 1 else 0 end) as ConvertedChats,
sum(case when PickedUpBy != AssignedToAgent and AssignedToAgent > 0 and PickedUpBy > 0 then 1 else 0 end) as MissedChats,
sum(case when AssignedToAgent > 0 then 1 else 0 end) as AssignedChats,
sum(case when LeadType=1 then 1 else 0 end) as SalesLeads
from
chats with (nolock)
left join leads on leads.id=chats.leadid
where
(chats.createdon >= DATEADD(d,0,DATEDIFF(d,0,GETDATE())) and chats.createdOn <= DATEADD(MI, -1*30, GETDATE()))
OR
(chats.CreatedOn >= DATEADD(d, -1, DATEDIFF(d, 0, GETDATE())) and chats.createdOn <= DATEADD(MI, -1*30, DATEADD(d, -1, GETDATE())))
OR
(chats.CreatedOn >= DATEADD(d, -7, DATEDIFF(d, 0, GETDATE())) and chats.createdOn <= DATEADD(MI, -1*30, DATEADD(d, -7, GETDATE())))
OR
(chats.CreatedOn >= DATEADD(d, -8, DATEDIFF(d, 0, GETDATE())) and chats.createdOn <= DATEADD(MI, -1*30, DATEADD(d, -8, GETDATE())))
If you want 4 rows for your query, you will need to add the date ranges as a case statement to your select, then group by that case statement. You should then get a row per value created by your case - which in this case should be the date ranges you want the stats split by.
When I run this query, it seems to work great when I run it against the date 2015-4-11. However, if I query against the last 3 days it returns the values in year, month, and week as the same. The day is accurate, but it doesn't seem to correctly add everything else.
declare #today date = '2015-1-1'
select
[Day Total] = sum(case when [AccountingDate] < dateadd(DAY, 1, #today) then [Amount] else 0 end),
[Week Total] = sum(case when [AccountingDate] < dateadd(WEEK, 1, #today) then [Amount] else 0 end),
[Month Total] = sum(case when [AccountingDate] < dateadd(MONTH, 1, #today) then [Amount] else 0 end),
[Year Total] = sum([Amount])
from
[Accounting].[dbo].[HandPay]
where
[AccountingDate] >= #today and [AccountingDate] < dateadd(year, 1, #today);
When you use a recent date, you're looking for values where the [AccountingDate] is less than some future date.
If you add a day/week/month to Today, then all data will be prior to those dates unless you have future data in your table:
declare #today date = '2015-05-12'
SELECT dateadd(DAY, 1, #today)
,dateadd(week, 1, #today)
,dateadd(month, 1, #today)
Returns: 2015-05-13, 2015-05-19, 2015-06-12
So [AccountingDate] is always less than those dates if your table only has data through today.
If you actually want to aggregate from Today to 1 day back, 1 week back, and 1 month back, you need to use -1 in your DATEADD(), use >, and modify your WHERE criteria, something like:
declare #today date = '2015-1-1'
select
[Day Total] = sum(case when [AccountingDate] > dateadd(DAY, -1, #today) then [Amount] else 0 end),
[Week Total] = sum(case when [AccountingDate] > dateadd(WEEK, -1, #today) then [Amount] else 0 end),
[Month Total] = sum(case when [AccountingDate] > dateadd(MONTH, -1, #today) then [Amount] else 0 end),
[Year Total] = sum([Amount])
from
[Accounting].[dbo].[HandPay]
where
[AccountingDate] <= #today and [AccountingDate] > dateadd(MONTH, -1, #today);
Note: When comparing a DATETIME to a DATE any time after midnight will be considered greater than the DATE value, so you'll want to make sure you're not excluding values, either by casting the DATETIME as DATE or ensuring you've accounted for the range properly, i.e.: < tomorrow's DATE instead of <= today's DATE to include records from today that have a time after 00:00:00.000