SQL Server null table join - sql

I have two tables one of it is LEAGUE, another is MATCH , in MATCH table there is a column as refLeague now I want to get total matches of week
For example
Id TotalMatches
-- ------------
1 12
2 0
3 6
If there is no match, I want to write 0 as table
SELECT l.Id ,COUNT(m.Id) as TotalMatches
FROM LEAGUE l
LEFT JOIN MATCH m ON l.Id = m.refLeauge
WHERE
m.MatchDate >= DATEADD(dd, DATEDIFF(dd, 1, GETDATE()) / 7 * 7 + 1, 0)
AND m.MatchDate < DATEADD(dd, DATEDIFF(dd, -6, GETDATE())/7 * 7 + 1, 0)
AND l.refSport = 1
GROUP BY l.Id
I wrote this query but it is not giving any result due to no rows in Match table, but it must be written 0
Example
Id TotalMatches
-- ------------
1 0
2 0
3 0
Where is my mistake?

Move the right table filters to ON condition
Non matching records will have NULL values in m.MatchDate which will be filtered by the condition in Where clause . Implicitly it will be converted to INNER JOIN. So the condition should be moved to ON clause which tells what are the records to be joined with LEAGUE instead of filtering the result
SELECT l.id,
Count(m.id) AS TotalMatches
FROM league l
LEFT JOIN match m
ON l.id = m.refleauge
AND m.matchdate >= Dateadd(dd, Datediff(dd, 1, Getdate()) / 7 * 7 + 1, 0)
AND m.matchdate < Dateadd(dd, Datediff(dd, -6, Getdate()) / 7 * 7 + 1, 0)
WHERE l.refsport = 1
GROUP BY l.id

The where is breaking the left join
SELECT l.Id, COUNT(m.Id) as TotalMatches
FROM LEAGUE l
LEFT JOIN MATCH m
ON l.Id = m.refLeauge
and m.MatchDate >= dateadd(dd, datediff(dd, 1, getdate()) / 7 * 7 + 1,0)
AND m.MatchDate < dateadd(dd, datediff(dd,-6, getdate()) / 7 * 7 + 1,0)
where l.refSport=1
GROUP BY l.Id
/ 7 * 7 = 1
When I started this answer the other answer was not yet posted

Related

Join table with dates list - include reference on NULLs

More brain freeze moments from me. I'm sure this will be an easy one.
I have two tables. One is a list of part usage by week. This is called TransactionsPerWeek and looks like this:
ItemPK xWeek xYear TotalQty
1234 2 2019 65
1234 4 2019 15
1234 5 2019 50
I also have a DateList table that has week numbers and years in it
xWeek xYear
1 2019
2 2019
3 2019
etc.
When I right join the two together on week and year I get
ItemPK xWeek xYear TotalQty
NULL 1 2019 0
1234 2 2019 65
NULL 3 2019 0
1234 4 2019 15
1234 5 2019 50
What I need is to have the ItemPK on every line, even if the TotalQty is 0. So in effect, I need:
ItemPK xWeek xYear TotalQty
1234 1 2019 0
1234 2 2019 65
1234 3 2019 0
1234 4 2019 15
1234 5 2019 50
This is my code...
SELECT itemfk,
dates.year,
dates.week,
isnull(transactionsperweek.TotalQty,0) as TotalQty
from (
SELECT iit.ItemFK,
year(iit.transactiondate) xYear,
datepart(wk,iit.transactiondate) xWeek,
abs(sum(iit.quantity)) TotalQty
from iteminventorytransaction iit
INNER JOIN ItemInventoryTransactionType iitt on ItemInventoryTransactionTypePK = iit.ItemInventoryTransactionTypeFK
where iit.itemfk = 5311
and iit.ItemInventoryTransactionTypeFK in (10,8)
and iit.TransactionDate BETWEEN
-- 1 year up to the sunday of last week
DateAdd(wk,-51,DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE()))
AND DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE())
AND Quantity < 0
group by iit.itemfk,
year(iit.transactiondate),
datepart(wk,iit.transactiondate)
) transactionsPerWeek
RIGHT JOIN (
select year,
week
from DatesList
where date > DateAdd(wk,-51,DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE()))
AND date < DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE())
group by year,
week
) Dates ON dates.week = transactionsPerWeek.xWeek
AND dates.year = transactionsPerWeek.xYear
where week not in (52,53)
Hope this is clear enough. Thanks in advance.
You can use recursive cte :
with cte as (
select 1 as id, max(xWeek) as maxwk
from TransactionsPerWeek
union all
select id + 1, maxwk
from cte c
where c.id < maxwk
)
select coalesce(wk.ItemPK, wk1.ItemPK) as ItemPK, c.id as xWeek, wk.xYear, wk.TotalQty
from cte c left join
TransactionsPerWeek wk
on wk.xWeek = c.id outer apply
( select top (1) wk1.ItemPK
from TransactionsPerWeek wk1
where wk1.xWeek >= c.id and wk1.xWeek is not null
order by wk1.xWeek
) wk1;
Ok, so I did what #larnu suggested and cross joined the item with the dates, then left joined it to the transactionsperweek table and it worked. Thank you.
This is my code now;
SELECT itempk, week, year
, ISNULL(transactionsPerWeek.TotalQty,0) as TotalQty
from item
CROSS JOIN
(
select year, week from DatesList where date >
DateAdd(wk,-51,DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE()))
AND date <
DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE())
group by year, week
) dates
LEFT JOIN
(
SELECT iit.ItemFK, year(iit.transactiondate) xYear, datepart(wk,iit.transactiondate) xWeek, abs(sum(iit.quantity)) TotalQty from iteminventorytransaction iit
INNER JOIN ItemInventoryTransactionType iitt on ItemInventoryTransactionTypePK = iit.ItemInventoryTransactionTypeFK
where iit.itemfk = 5311 and iit.ItemInventoryTransactionTypeFK in (10,8)
and iit.TransactionDate BETWEEN
-- 1 year up to the sunday of last week
DateAdd(wk,-51,DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE()))
AND
DATEADD(day,-1 - (DATEPART(weekday, GETDATE()) + ##DATEFIRST - 2) % 7,GETDATE())
AND Quantity < 0
group by iit.itemfk, year(iit.transactiondate), datepart(wk,iit.transactiondate)
) transactionsPerWeek
ON itempk = transactionsperweek.ItemFK and transactionsPerWeek.xYear = dates.year and transactionsPerWeek.xWeek = dates.week
where itempk = 5311
Use a cross join to generate the rows and a left join to bring in the results you already have.
Your question explicitly states that you have two tables. Hence, I don't know what your SQL code is doing, because it is not referencing those tables. So, based on the description:
select i.ItemPK, d.xWeek, d.xYear,
coalesce(TotalQty, 0) as TotalQty
from (select distinct itemPK from TransactionsPerWeek
) i cross join
DateList d left join
TransactionsPerWeek t
on t.itemPK = i.itemPK and
t.xWeek = d.xWeek and
t.xYear = d.xYear;
Of course if the "tables" are really subqueries, then I would recommend using CTEs and still this basic query structure.

Query multiple aggregations in a single row

I want a query that returns results from 3 months, 6 months and 12 months in their own column.
3 | 6 | 12
V1| V2| V3
I have a query that will give me any one of these results:
Code to get one value:
SELECT SUM(CONVERT(bigint,R.FileSize)) / (1024*1024) AS '3'
FROM Revisions R
JOIN Documents D ON D.DocumentID = R.DocumentID
WHERE R.Date BETWEEN dateadd(month, -3, GETDATE()) AND getdate()
Results:
3
205
I tried to embed the SQL query and combine them.
SELECT b.3, SUM(CONVERT(bigint,R.FileSize)) / (1024*1024) AS '6'
FROM Revisions R2
JOIN Documents D2 ON D2.DocumentID = R2.DocumentID
FULL OUTER JOIN b ON b.3 = 6
(SELECT SUM(CONVERT(bigint,R.FileSize)) / (1024*1024) AS '3'
FROM Revisions R
JOIN Documents D ON D.DocumentID = R.DocumentID
WHERE R.Date BETWEEN dateadd(month, -3, GETDATE()) AND getdate()) b
WHERE R2.Date BETWEEN dateadd(month, -6, GETDATE()) AND getdate();
I think you want conditional aggregation:
SELECT SUM(CASE WHEN R.Date BETWEEN dateadd(month, -3, GETDATE()) AND getdate()
THEN CONVERT(bigint, R.FileSize)) / (1024*1024)
END) AS filesize_3,
SUM(CASE WHEN R.Date BETWEEN dateadd(month, -6, GETDATE()) AND getdate()
THEN CONVERT(bigint, R.FileSize)) / (1024*1024)
END) AS filesize_6,
SUM(CASE WHEN R.Date BETWEEN dateadd(month, -9, GETDATE()) AND getdate()
THEN CONVERT(bigint, R.FileSize)) / (1024*1024)
END) AS filesize_9
FROM Revisions R JOIN
Documents D
ON D.DocumentID = R.DocumentID

Selecting multiple subqueries

I have subqueries that need to return different results. Each subqueries used different aggregate functions like SUM() AND COUNT(*). What I did is I encapsulate them with SELECT (SELECT subquery, SELECT subquery) not sure if this possible.
Expected result:
TwoYears
123
5
SELECT(
(SELECT
(SELECT SUM(AHT)
FROM
(
SELECT
CASE
WHEN DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE()) >= 2 AND (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 2 OR (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 1
THEN [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Value]
END AS AHT
FROM [AgentProfile_CRT].[dbo].[uvw_AHTMaster] WHERE [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Month] = 'January' AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Year] = 2018 AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[AccountID] = 8 AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[LOBID] = 23
) f
WHERE AHT = AHT ) AS TwoYears),
(SELECT
(SELECT COUNT(*) AS TwoYears
FROM
(
SELECT
CASE
WHEN DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE()) >= 2 AND (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 2 OR (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 1
THEN 'Good'
END AS Result
FROM [AgentProfile_CRT].[dbo].[uvw_AHTMaster] WHERE [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Month] = 'January' AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Year] = 2018 AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[AccountID] = 8 AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[LOBID] = 23
) f
WHERE Result = 'Good') AS TwoYears)
) a
You need to make a union all and remove some of your subselects.
Like this:
SELECT SUM(AHT) as TwoYears
FROM (
SELECT CASE
WHEN DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE()) >= 2
AND (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 2
OR (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 1
THEN [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Value]
END AS AHT
FROM [AgentProfile_CRT].[dbo].[uvw_AHTMaster]
WHERE [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Month] = 'January'
AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Year] = 2018
AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[AccountID] = 8
AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[LOBID] = 23
) f
WHERE AHT = AHT
union all
SELECT COUNT(*) AS TwoYears
FROM (
SELECT CASE
WHEN DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE()) >= 2
AND (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 2
OR (DATEDIFF(year, [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[HireDate], GETDATE())) <= 1
THEN 'Good'
END AS Result
FROM [AgentProfile_CRT].[dbo].[uvw_AHTMaster]
WHERE [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Month] = 'January'
AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[Year] = 2018
AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[AccountID] = 8
AND [AgentProfile_CRT].[dbo].[uvw_AHTMaster].[LOBID] = 23
) f
WHERE Result = 'Good'

How to write SQL for stock quantity that requires calculation from previous orders

I have two tables, one for current total stock of products and one for the product orders.
STOCK_TB
PRODUCT_ID STOCK_QTY
A 20
B 15
C 10
ORDER_TB
ORDER_DATE PRODUCT_ID ORDER QTY
2015-03-01 A 5
2015-03-02 A 3
2015-03-02 B 4
2015-03-03 C 1
2015-03-04 C 3
I'd like to select data for a monthly-stock quantity report that looks like this. Assume the report was built on March 5th
Stock Quantity of March:
Daily Stock Qty
Product ID 1 2 3 4 5 6 7 ... 28 29 30 31
A 23 20 20 20 20 0 0 0 0 0 0
B 19 15 15 15 15 0 0 0 0 0 0
C 14 14 13 10 10 0 0 0 0 0 0
The stock quantity for previous dates is based on the closing day (I.E: March 2nd above refers to March 2nd 23:59:99.999)
Any dates that goes beyond the current date will have a quantity of 0
We don't have a table for keeping daily-stocks, just the current stock. So this means for getting stocks of previous dates, I'd have to add the amount of product orders backwards.
How do you write this type of query? For the date columns, I can have them fixed from 1 to 31, since I can just hide the unused dates based on the month in my application. But I'm not really sure how I can write logic in SQL for adding order quantity to the current stock on previous dates.
Query example for 6 days (the other 25 days are the same :-)
DECLARE #FirstOfMonth AS DATETIME = DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
SELECT
CASE WHEN DAY(GETDATE()) < 1 THEN 0 ELSE S.STOCK_QTY + ISNULL((SELECT SUM(O.ORDER_QTY) FROM ORDER_TB O WHERE O.PRODUCT_ID = S.PRODUCT_ID AND O.ORDER_DATE > DATEADD(day, 0, #FirstOfMonth)), 0) END _1,
CASE WHEN DAY(GETDATE()) < 2 THEN 0 ELSE S.STOCK_QTY + ISNULL((SELECT SUM(O.ORDER_QTY) FROM ORDER_TB O WHERE O.PRODUCT_ID = S.PRODUCT_ID AND O.ORDER_DATE > DATEADD(day, 1, #FirstOfMonth)), 0) END _2,
CASE WHEN DAY(GETDATE()) < 3 THEN 0 ELSE S.STOCK_QTY + ISNULL((SELECT SUM(O.ORDER_QTY) FROM ORDER_TB O WHERE O.PRODUCT_ID = S.PRODUCT_ID AND O.ORDER_DATE > DATEADD(day, 2, #FirstOfMonth)), 0) END _3,
CASE WHEN DAY(GETDATE()) < 4 THEN 0 ELSE S.STOCK_QTY + ISNULL((SELECT SUM(O.ORDER_QTY) FROM ORDER_TB O WHERE O.PRODUCT_ID = S.PRODUCT_ID AND O.ORDER_DATE > DATEADD(day, 3, #FirstOfMonth)), 0) END _4,
CASE WHEN DAY(GETDATE()) < 5 THEN 0 ELSE S.STOCK_QTY + ISNULL((SELECT SUM(O.ORDER_QTY) FROM ORDER_TB O WHERE O.PRODUCT_ID = S.PRODUCT_ID AND O.ORDER_DATE > DATEADD(day, 4, #FirstOfMonth)), 0) END _5,
CASE WHEN DAY(GETDATE()) < 6 THEN 0 ELSE S.STOCK_QTY + ISNULL((SELECT SUM(O.ORDER_QTY) FROM ORDER_TB O WHERE O.PRODUCT_ID = S.PRODUCT_ID AND O.ORDER_DATE > DATEADD(day, 5, #FirstOfMonth)), 0) END _6
FROM STOCK_TB S
Note that I've used > DATEADD instead of >= DATEADD but I'm not so sure... The order you put the first of the month when are counted?
Second solution, but I don't think the complexity will change very much:
DECLARE #FirstOfMonth AS DATETIME = DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
DECLARE #Today AS DATETIME = DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
;WITH Days(d, dat) AS
(
SELECT 1, #FirstOfMonth
UNION ALL
SELECT d+1, DATEADD(day, 1, dat) FROM Days WHERE d < DATEPART(day, #today)
)
, Work1 AS (
SELECT PRODUCT_ID, STOCK_QTY + ISNULL((SELECT SUM(O.ORDER_QTY) FROM ORDER_TB O WHERE O.PRODUCT_ID = S.PRODUCT_ID AND O.ORDER_DATE > dat), 0) STOCK_TB, d FROM STOCK_TB S, Days
)
SELECT PRODUCT_ID,
ISNULL(MAX(CASE WHEN d = 1 THEN STOCK_TB END), 0) _1,
ISNULL(MAX(CASE WHEN d = 2 THEN STOCK_TB END), 0) _2,
ISNULL(MAX(CASE WHEN d = 3 THEN STOCK_TB END), 0) _3,
ISNULL(MAX(CASE WHEN d = 4 THEN STOCK_TB END), 0) _4,
ISNULL(MAX(CASE WHEN d = 5 THEN STOCK_TB END), 0) _5,
ISNULL(MAX(CASE WHEN d = 6 THEN STOCK_TB END), 0) _6,
ISNULL(MAX(CASE WHEN d = 7 THEN STOCK_TB END), 0) _7,
ISNULL(MAX(CASE WHEN d = 8 THEN STOCK_TB END), 0) _8
FROM Work1 GROUP BY PRODUCT_ID
Here I use a fancy recursive query to build a table of days 1...(today), then I build a Work1 intermediate that has all the stock quantities day by day (so x products * y days rows), and then I group them
Third possibility: double recursive query (one to calculate the numbers 1...31 and one to do a running total), plus the final GROUP BY nearly identical to the previous example.
DECLARE #FirstOfMonth AS DATETIME = DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
DECLARE #Today AS DATETIME = DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)
;WITH Days(d, dat) AS
(
SELECT DATEPART(day, #Today), #Today dat
UNION ALL
SELECT d-1, DATEADD(day, -1, dat) dat
FROM Days
WHERE d > 1
)
# Product Days x STOCK_TB with a LEFT JOIN on ORDER_TB.
, Work1 AS (
SELECT S.PRODUCT_ID, d, dat, S.STOCK_QTY, ISNULL(O.ORDER_QTY, 0) ORDER_QTY
FROM Days
CROSS JOIN STOCK_TB S # Full cartesian product, JOIN without conditions
LEFT JOIN ORDER_TB O ON dat = O.ORDER_DATE AND S.PRODUCT_ID = O.PRODUCT_ID
)
# Second recursive query to do the running total
, Days2(PRODUCT_ID, d, dat, STOCK_QTY) AS
(
SELECT PRODUCT_ID, d, dat, STOCK_QTY
FROM Work1
WHERE d = DATEPART(day, #Today)
UNION ALL
SELECT d.PRODUCT_ID, d.d - 1, w.dat, d.STOCK_QTY + w.ORDER_QTY
FROM Days2 d
INNER JOIN Work1 w ON d.PRODUCT_ID = w.PRODUCT_ID AND d.d /* - 1 */ = w.d
WHERE d.d > 1
)
SELECT PRODUCT_ID,
ISNULL(MAX(CASE WHEN d = 1 THEN STOCK_QTY END), 0) _1,
ISNULL(MAX(CASE WHEN d = 2 THEN STOCK_QTY END), 0) _2,
ISNULL(MAX(CASE WHEN d = 3 THEN STOCK_QTY END), 0) _3,
ISNULL(MAX(CASE WHEN d = 4 THEN STOCK_QTY END), 0) _4,
ISNULL(MAX(CASE WHEN d = 5 THEN STOCK_QTY END), 0) _5,
ISNULL(MAX(CASE WHEN d = 6 THEN STOCK_QTY END), 0) _6,
ISNULL(MAX(CASE WHEN d = 7 THEN STOCK_QTY END), 0) _7,
ISNULL(MAX(CASE WHEN d = 8 THEN STOCK_QTY END), 0) _8
FROM Days2 GROUP BY PRODUCT_ID
Note the /* - 1 */ commented part. Uncommenting it you control how the value of the first of the month is used.

Using a sub query in column list

I would like to create a query that would count how many records were created in the last 7, 14 and 28 days. My result would return something like:
7Days 14Days 28Days
21 35 56
I know how to for each timepsan e.g. 7 days, but I do I capture all three in one query?
select count(*) from Mytable
where Created > DATEADD(day,-8, getdate())
Also not pretty, but doesn't rely on subqueries (table/column names are from AdventureWorks). The case statement returns 1 if it falls within your criteria, 0 otherwise - then you just sum the results :
select sum(case when datediff(day, modifieddate, getdate()) <= 7
then 1 else 0 end) as '7days',
sum(case when datediff(day, modifieddate, getdate()) > 7
and datediff(day, modifieddate, getdate()) <= 14
then 1 else 0 end) as '14days',
sum(case when datediff(day, modifieddate, getdate()) > 14
and datediff(day, modifieddate, getdate()) <= 28
then 1 else 0 end) as '28days'
from sales.salesorderdetail
Edit: Updated the datediff function - the way it was written, it would return a negative number (assuming modifieddate was in the past) causing all items to fall under the first case. Thanks to Andriy M for pointing that out
It isn't the prettiest code in the world, but it does the trick. Try selecting from three subqueries, one for each range.
select * from
(select COUNT(*) as Cnt from Log_UrlRewrites where CreateDate >= DATEADD(day, -7, getdate())) as Seven
inner join (select COUNT(*) as Cnt from Log_UrlRewrites where CreateDate >= DATEADD(day, -14, getdate())) as fourteen on 1 = 1
inner join (select COUNT(*) as Cnt from Log_UrlRewrites where CreateDate >= DATEADD(day, -28, getdate())) as twentyeight on 1 = 1
select
(
select count(*)
from Mytable
where Created > DATEADD(day,-8, getdate())
) as [7Days],
(
select count(*)
from Mytable
where Created > DATEADD(day,-15, getdate())
) as [14Days],
(
select count(*)
from Mytable
where Created > DATEADD(day,-29, getdate())
) as [28Days]
SELECT
[7Days] = COUNT(CASE UtmostRange WHEN 7 THEN 1 END),
[14Days] = COUNT(CASE UtmostRange WHEN 14 THEN 1 END),
[28Days] = COUNT(CASE UtmostRange WHEN 28 THEN 1 END)
FROM (
SELECT
*,
UtmostRange = CASE
WHEN Created > DATEADD(day, -8, GETDATE()) THEN 7
WHEN Created > DATEADD(day, -15, GETDATE()) THEN 14
WHEN Created > DATEADD(day, -29, GETDATE()) THEN 28
END
FROM Mytable
) s