Query multiple aggregations in a single row - sql

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

Related

Recursive query?

Hello everybody i'm currently stuck with a query for an ssrs report.
The database is a ticket registration for an helpdesk. So every day techs from the cds team log tickets. If they couldn't resolve the ticket they send it to an other team.
I'm looking for a query who retrace the backlog (non closed tickets) for each month and each team at the end of the month.
Ex :
May 26 17h ticket open by the helpdesk
May 27 8h ticket goes to Techsupport N2
June 3 ticket goes to Tech N3
July 2 ticket closed
I need to retrieve this :
Helpdesk May 0 June 0
N2 May 1 June 0
N3 May 0 June 1
database structure :
Table Appel
Noappel
C_equipe (last affected team)
Table actions
Noappel
Noaction
type_action (affect when goes to an other team Clos when closed)
C_equipe (team who done the action)
i made something based on a query found on the web but it works on weeks not months.
DECLARE #DR DATETIME
DECLARE #SM INTEGER
SET #SM=5
SET #DR=getdate()
SELECT T.* FROM (SELECT A.IDT_APPEL AS NOTICKET,
DEBUT.C_ACTION AS C_DEBUT,
FIN.C_ACTION AS C_FIN,
RS.DF_SEM AS F_TEST,
RS.NUM_SEMAINE AS NUM_SEMAINE,
E.L_EQUIPE AS EQUIPETICKET,
EP.L_EQUIPE AS EQUIPESUP,
A.C_UTIL_INT,
CONCAT(util.N_UTIL,' ',util.PRE_UTIL) AS INTERVENANT,
CASE
WHEN Datepart(ISO_WEEK, FIN.D_CREATION) = RS.NUM_SEMAINE
AND Datediff(DAY, FIN.D_CREATION, RS.DF_SEM) < 7
AND FIN.C_TACTION = 'SYS_EQUIPE'
AND Isnull(UTIL.C_ISIPARC, '0') <> '666' THEN 1
ELSE 0
END AS COND_TR,
CASE
WHEN Datepart(ISO_WEEK, FIN.D_CREATION) = RS.NUM_SEMAINE
AND Datediff(DAY, FIN.D_CREATION, RS.DF_SEM) < 7
AND FIN.C_TACTION = 'SYS_EQUIPE'
AND Isnull(UTIL.C_ISIPARC, '0') = '666' THEN 1
ELSE 0
END AS COND_REJ,
CASE
WHEN FIN.C_TACTION IN('SYS_CLOS_TECH','SYS_CLOS')
AND Datepart(ISO_WEEK, FIN.D_CREATION) = RS.NUM_SEMAINE
AND Datediff(DAY, FIN.D_CREATION, RS.DF_SEM) < 7 THEN 1
ELSE 0
END AS COND_CLOS,
CASE
WHEN Datepart(ISO_WEEK, DEBUT.D_CREATION) = RS.NUM_SEMAINE
AND Datediff(DAY, DEBUT.D_CREATION, RS.DF_SEM) < 7 THEN 1
ELSE 0
END AS NB_TICKET_ENTRE,
CASE
WHEN ( ( FIN.D_CREATION IS NULL
OR FIN.D_CREATION > RS.DF_SEM )
AND DEBUT.D_CREATION < RS.DF_SEM ) THEN ( CASE
WHEN Datediff(DAY, DEBUT.D_CREATION, RS.DF_SEM) - 2 < 5 THEN '05'
WHEN Datediff(DAY, DEBUT.D_CREATION, RS.DF_SEM) - 2 >= 5
AND Datediff(DAY, DEBUT.D_CREATION, RS.DF_SEM) - 2 < 10 THEN '10'
WHEN Datediff(DAY, DEBUT.D_CREATION, RS.DF_SEM) - 2 >= 10
AND Datediff(MONTH, DEBUT.D_CREATION, RS.DF_SEM) < 1 THEN '30'
WHEN Datediff(MONTH, DEBUT.D_CREATION, RS.DF_SEM) >= 1 THEN '30+'
ELSE NULL
END )
ELSE NULL
END AS F_NONCLOS,
CASE
WHEN Datepart(ISO_WEEK, FIN.D_CREATION) = RS.NUM_SEMAINE
AND Datediff(DAY, FIN.D_CREATION, RS.DF_SEM) < 7 THEN ( CASE
WHEN Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) < 1 THEN '01'
WHEN Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) >= 1
AND Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) < 2 THEN '02'
WHEN Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) >= 2
AND Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) < 5 THEN '05'
WHEN Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) >= 5
AND Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) < 15 THEN '15'
WHEN Datediff(DAY, DEBUT.D_CREATION, FIN.D_CREATION) >= 15 THEN '15+'
ELSE NULL
END )
ELSE NULL
END AS F_CLOS,
DEBUT.D_CREATION AS DEBUT,
FIN.D_CREATION AS FIN,
RS.YEAR AS YEARS
FROM APPEL A
INNER JOIN (SELECT B.NO_APPEL,
B.C_ACTION,
B.D_CREATION,
B.C_EQUIPE,
B.C_TACTION,
Lead(B.C_ACTION, 1)
OVER (
PARTITION BY B.NO_APPEL
ORDER BY B.C_ACTION) AS FIN_C_ACTION
FROM ACTIONS B WITH (NOLOCK)
WHERE B.C_TACTION IN ( 'SYS_EQUIPE', 'SYS_CLOS_TECH', 'SYS_REOUVERT','SYS_CLOS' )
AND ( CAST(B.D_CREATION AS DATE)< Dateadd(week, Datediff(week, 0, Dateadd(WEEK, 0, #DR)), 0) )) DEBUT
ON ( A.NO_APPEL = DEBUT.NO_APPEL
AND DEBUT.C_EQUIPE IN('ETUD_MET_BILIZI')
AND DEBUT.C_TACTION IN( 'SYS_EQUIPE', 'SYS_REOUVERT' ) )
LEFT JOIN ACTIONS FIN WITH (NOLOCK)
ON ( FIN.C_ACTION = DEBUT.FIN_C_ACTION )
LEFT JOIN UTILISATEUR UTIL WITH (NOLOCK)
ON ( UTIL.C_UTIL = FIN.C_UTIL )
INNER JOIN EQUIPE E WITH (NOLOCK)
ON DEBUT.C_EQUIPE = E.C_EQUIPE
INNER JOIN EQUIPE EP WITH (NOLOCK)
ON E.C_EQUIPE_PERE = EP.C_EQUIPE
INNER JOIN (SELECT DISTINCT Datepart(ISO_WEEK, P.D_JOUR) AS Num_semaine,
Dateadd(SECOND, 59, Dateadd(MINUTE, 59, Dateadd(HOUR, 23, Dateadd(DAY, -1, Dateadd(week, Datediff(week, 0, P.D_JOUR) + 1, 0))))) AS DF_SEM,
YEAR(P.D_JOUR) AS YEAR
FROM PLANNINGS P WITH (NOLOCK)
INNER JOIN TCALEND TC WITH (NOLOCK)
ON TC.C_TCALEND = P.C_TCALEND
AND TC.F_TCALENDSTD = 1
WHERE ( C_TPERIOD <> 3
AND C_TPERIOD <> 9 )) RS
ON ( ( FIN.D_CREATION > Dateadd(DAY, -7, RS.DF_SEM)
OR FIN.D_CREATION IS NULL )
AND (CAST( RS.DF_SEM AS DATE) >= Dateadd(week, Datediff(week, 0, Dateadd(WEEK, - #SM, #DR)), 0)
AND CAST(RS.DF_SEM AS DATE) <= Dateadd(week, Datediff(week, 0, Dateadd(WEEK, 0,#DR)), 0) ) )
WHERE (A.C_NATURE = 'INC' OR A.C_NATURE = 'DMD')
AND ( A.D_CLOTTECH >= Dateadd(week, Datediff(week, 0, Dateadd(WEEK, - #SM, #DR)), 0)
OR A.D_CLOTTECH IS NULL )
UNION
SELECT DISTINCT NULL IDT_APPEL,
NULL C_DEBUT,
NULL C_FIN,
Dateadd(SECOND, 59, Dateadd(MINUTE, 59, Dateadd(HOUR, 23, Dateadd(DAY, -1, Dateadd(week, Datediff(week, 0, P.D_JOUR) + 1, 0))))) AS DF_SEM,
Datepart(ISO_WEEK, P.D_JOUR) AS Num_semaine,
NULL EQUIPETICKET,
NULL EQUIPESUP,
NULL C_UTIL_INT,
NULL INTERVENANT,
0 COND_TR,
0 COND_REJ,
0 COND_CLOS,
0 NB_TICKET_ENTRE,
NULL F_NONCLOS,
NULL F_CLOS,
NULL,
NULL,
--YEAR(P.D_JOUR) AS YEARS
case when Datepart(ISO_WEEK, P.D_JOUR)=1 then YEAR(getdate()) ELSE YEAR(P.D_JOUR) end AS YEARS
FROM PLANNINGS P WITH (NOLOCK)
INNER JOIN TCALEND TC WITH (NOLOCK)
ON TC.C_TCALEND = P.C_TCALEND
AND TC.F_TCALENDSTD = 1
WHERE ( C_TPERIOD <> 3
AND C_TPERIOD <> 9 )
AND Dateadd(SECOND, 59, Dateadd(MINUTE, 59, Dateadd(HOUR, 23, Dateadd(DAY, -1, Dateadd(week, Datediff(week, 0, P.D_JOUR) + 1, 0))))) >= Dateadd(week, Datediff(week, 0, Dateadd(WEEK, - #SM, #DR)), 0)
AND Dateadd(SECOND, 59, Dateadd(MINUTE, 59, Dateadd(HOUR, 23, Dateadd(DAY, -1, Dateadd(week, Datediff(week, 0, P.D_JOUR) + 1, 0))))) <= Dateadd(week, Datediff(week, 0, Dateadd(WEEK, 0, #DR)), 0)) T ORDER BY T.YEARS ASC
Thanks

Perform multiple SUMs on same column but for multiple date range periods

Given the following table:
id member_id paid_amount trx_date
-------------------------------------------
x 1 100 2019-07-01
x 2 50 2019-07-02
x 1 150 2019-07-05
x 2 70 2019-07-08
x 1 90 2019-08-01
I would like to partition this data and get the sum for each member in 30 day intervals starting at the day of query execution and going backwards. My end result should look like this if I execute the query on the 10th of the month:
member_id paid_amount from
----------------------------------
1 250 2019-06-10 (Sum of paid_amount from 06-10 to 07-10 for member 1)
2 120 2019-06-10 (Sum of paid_amount from 06-10 to 07-10 for member 2)
1 90 2019-07-10 (Sum of paid_amount from 07-10 to 08-10 for member 1)
Basically I would like to sum paid_amount depending on the date where the query ran, in this example 10th Sep 2019, so I want the sum for each member for the following periods
2019-08-10 --> 2019-09-10
2019-07-10 --> 2019-08-10
2019-06-10 --> 2019-07-10
2019-05-10 --> 2019-06-10
etc..
This is what I came up with so far:
SELECT
member_id,
SUM(paid_amount),
p
FROM
(
SELECT
member_id,
paid_amount,
CASE WHEN trx_date BETWEEN DATEADD(MONTH, -1, GETUTCDATE()) AND GETUTCDATE() THEN FORMAT(DATEADD(MONTH, -1, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -2, GETUTCDATE()) AND DATEADD(MONTH, -1, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -2, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -3, GETUTCDATE()) AND DATEADD(MONTH, -2, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -3, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -4, GETUTCDATE()) AND DATEADD(MONTH, -3, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -4, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -5, GETUTCDATE()) AND DATEADD(MONTH, -4, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -5, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -6, GETUTCDATE()) AND DATEADD(MONTH, -5, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -6, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -7, GETUTCDATE()) AND DATEADD(MONTH, -6, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -7, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -8, GETUTCDATE()) AND DATEADD(MONTH, -7, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -8, GETUTCDATE()), 'yyyy-MM-dd')
WHEN trx_date BETWEEN DATEADD(MONTH, -9, GETUTCDATE()) AND DATEADD(MONTH, -8, GETUTCDATE()) THEN FORMAT(DATEADD(MONTH, -9, GETUTCDATE()), 'yyyy-MM-dd')
-- and many more WHEN clauses ...
END AS p
FROM
my_table
) AS t
GROUP BY
t.member_id,
t.p
While the above works, there are a few problems with it. First, I need to define so many WHEN clauses because I don't know how far the data goes back to. The second issue is that this query starts slowing down a bit when my table is large.
I am using this query for a view so some options are off limit. Is there a better version of this that is smaller and possibly offer better performance?
You can use a recursive CTE to generate the date periods that cover all the data in your table:
WITH md (min_trx_date) AS (
SELECT MIN(trx_date) AS min_trx_date FROM my_table
),
cte (trx_date_end, trx_date_start) AS (
SELECT convert(date, GETUTCDATE()) AS trx_date_end,
convert(date, DATEADD(MONTH, -1, GETUTCDATE())) AS trx_date_start
UNION ALL
SELECT DATEADD(MONTH, -1, trx_date_end),
DATEADD(MONTH, -1, trx_date_start)
FROM cte
JOIN md ON cte.trx_date_start > md.min_trx_date
)
and then JOIN that CTE to your table to get the payments:
SELECT m.member_id,
SUM(m.paid_amount),
cte.trx_date_start
FROM my_table m
JOIN cte ON m.trx_date BETWEEN cte.trx_date_start AND cte.trx_date_end
GROUP BY member_id, trx_date_start
Demo on dbfiddle
You can try to use cte recursive make calendar table.
use LEAD get next month date, then do join with table.
Query 1:
WITH CTE AS(
SELECT CAST('2019-01-10' AS DATE) fromDt,
CAST('2019-12-10' AS DATE) toDt
UNION ALL
SELECT dateadd(month,1,fromDt),toDt
FROM CTE
WHERE dateadd(month,1,fromDt) < toDt
),CTE2 AS(
SELECT fromDt,LEAD(fromDt) OVER(ORDER BY fromDt) nextMonth
FROM CTE
)
SELECT member_id,
fromDt,
SUM(paid_amount) paid_amount
FROM CTE2 c JOIN T t
on t.trx_date BETWEEN c.fromDt and c.nextMonth
GROUP BY member_id,fromDt
Results:
| member_id | fromDt | paid_amount |
|-----------|------------|-------------|
| 1 | 2019-06-10 | 250 |
| 2 | 2019-06-10 | 120 |
| 1 | 2019-07-10 | 90 |
You can replace your function computing p with something simpler, like datediff(day, trx_date, getutcdate()) / 30. First 30-day interval backwards from now will produce value 0, second - 1, etc.
Select member_id, paid_amount, trx_date as from from TABLE
a join Table b where DateDiff(a.trx_date, b.trx_date) =30
group by member _id

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'

SQL Server null table join

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

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