我正在使用SQL Server 2008 R2。
我正在查询医院预约老虎机的表格,并尝试返回一个列表,列出特定医生被标记为已预订的预约时段,按周数/年分组。
有些星期的例子还没有任何预约约会,但我希望结果列出所有即将到来的几周,即使预订的预约时段的数量为零。
我正在寻找的输出是这样的:
-------------------------------------------
Year | Week Number | Number of Booked Slots
-------------------------------------------
2017 | 48 | 10
2017 | 49 | 0
2017 | 50 | 4
2017 | 51 | 2
2017 | 52 | 0
2018 | 1 | 5
我知道聚合结果的标准选择不会显示记录数为零的那几周,因为没有什么可以返回 - 所以我试图通过使用cte首先生成一个列表来解决这个问题所有即将到来的几周。
但是,尽我所能,我无法让查询显示零周......
我已经看到了许多与此类似问题的解决方案,但是尽管进行了实验,我还是无法将它们应用于我的特定问题(包括SQL Count to include zero values)
这是我到目前为止所写的查询的最新版本。
WITH CTE_Dates AS
(
SELECT DISTINCT Slot_Start_Date AS cte_date
FROM [Outpatients.vw_OP_Clinic_Slots WITH (NOLOCK)
)
SELECT
DATEPART(year,OPCS.Slot_Start_Date) [Year]
,DATEPART(week,OPCS.Slot_Start_Date) [Week Number]
,count(OPCS.Slot_Start_Date) [Number of Booked Slots]
FROM
Outpatients.vw_OP_Clinic_Slots OPCS WITH (NOLOCK)
LEFT OUTER JOIN CTE_Dates ON OPCS.Slot_Start_Date=CTE_Dates.cte_date
LEFT OUTER JOIN Outpatients.vw_OP_Clinics CLIN ON OPCS.Clinic_Code=CLIN.Clinic_Code
WHERE
OPCS.Slot_Start_Date >= '14/08/2017'
AND OPCS.Booked_Flag = 'Y'
AND CLIN.Lead_Healthcare_Professional_Name = 'Dr X'
GROUP BY
DATEPART(year,OPCS.Slot_Start_Date)
,DATEPART(week,OPCS.Slot_Start_Date)
ORDER BY
DATEPART(year,OPCS.Slot_Start_Date)asc
,DATEPART(week,OPCS.Slot_Start_Date)asc
它返回给我的结果是正确的,但我只是需要它将那些周列入计数为零的列表中。
任何人都可以解释我哪里出错了吗?我猜我没有正确加入cte,但我尝试了左右连接,产生相同的结果。我也尝试通过swopping上面的查询语句和cte around来反转查询,但这也不起作用。
感谢任何人可以建议的任何指导。
答案 0 :(得分:1)
只有RIGHT JOIN
@ListOfWeeks
表到您拥有的结果集:
DECLARE @ListOfWeeks TABLE ([Week_No] int, [Year_Number] int);
DECLARE @i tinyint = 1, @y int = 2010;
WHILE @i <= 52 AND @y < 2018
BEGIN
INSERT INTO @ListOfWeeks([Week_No], [Year_Number]) VALUES (@i, @y);
IF @i = 52 BEGIN
SET @i = 0
SET @y +=1
END
SET @i += 1
END
SELECT * FROM @ListOfWeeks
WITH [Your_Part] AS(
SELECT
DATEPART(year,OPCS.Slot_Start_Date) [Year]
,DATEPART(week,OPCS.Slot_Start_Date) [Week Number]
,count(OPCS.Slot_Start_Date) [Number of Booked Slots]
FROM
Outpatients.vw_OP_Clinic_Slots OPCS WITH (NOLOCK)
LEFT OUTER JOIN CTE_Dates ON OPCS.Slot_Start_Date=CTE_Dates.cte_date
LEFT OUTER JOIN Outpatients.vw_OP_Clinics CLIN ON OPCS.Clinic_Code=CLIN.Clinic_Code
WHERE
OPCS.Slot_Start_Date >= '14/08/2017'
AND OPCS.Booked_Flag = 'Y'
AND CLIN.Lead_Healthcare_Professional_Name = 'Dr X'
GROUP BY
DATEPART(year,OPCS.Slot_Start_Date)
,DATEPART(week,OPCS.Slot_Start_Date)
),
SELECT xxx.[Year_Number], xxx.[Week_No], yp.[Number of Booked Slots]
FROM [Your_Part] yp
RIGHT JOIN @ListOfWeeks xxx ON yp.[Year] = xxx.[Year_Number] AND yp.[Week Number] = xxx.[Week_No]
答案 1 :(得分:0)
IF OBJECT_ID(N'tempdb..##cal_weeks_temp', N'U') IS NOT NULL
DROP TABLE ##cal_weeks_temp;
create table ##cal_weeks_temp (date_of_week date, week_num int)
declare @start_date date
declare @end_date date
set @start_date='01/01/2017'
set @end_date='12/31/2018'
while @start_date<@end_date
begin
set @start_date=dateadd(day,1,@start_date)
insert into ##cal_weeks_temp values (@start_date,DATEPART(week,@start_date))
end
select YEAR(t1.date_of_week) 'YEAR',t1.week_num,
sum(case convert(varchar,t2.BookedTime,105) when convert(varchar,t1.date_of_week,105) then 1 else 0 end) 'count'
from ##cal_weeks_temp t1
left join Your_Table t2
on convert(varchar,t2.BookedTime,105)=convert(varchar,t1.date_of_week,105)
group by YEAR(t1.date_of_week) ,t1.week_num
order by YEAR(t1.date_of_week) ,t1.week_num