2017-08-17 102 views
3

我正在使用SQL Server 2008 R2。SQL:按连续日期计算记录数,即使某个日期不存在记录

我在查询一张医院预约插槽表,并试图返回特定医生有多少预约插槽的列表被标记为预订,按周/年编组。

有些星期没有任何预约约会,但我希望结果列出所有即将到来的星期,即使预约的预约时间段数为零。

我要找的输出是沿着这些线路:

------------------------------------------- 
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来反转查询,但是这也不起作用。

欣赏任何人可以建议的指导。

回答

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] 
+0

感谢您的帮助@Bartosz X.不幸的是,这是不是为我工作 - 我得到的错误'操作数类型冲突:日期与int不兼容也许我没有正确的连接语法?我已经使用了:'RIGHT JOIN @ListOfWeeks ON OPCS.Slot_Start_Date = Week_No'这是正确的吗? – Jon295087

+0

不,加入week_number而不是 –

+0

对不起@Bartosz_X我仍然无法完成这项工作。我试着:'RIGHT JOIN @ListOfWeeks ON DATEPART(week,OPCS.Slot_Start_Date)= Week_No',但它仍然给我没有零星期的相同结果。我尝试加入[Week_Number],但这会产生错误:'Week_Number'附近的语法错误。'我假设因为[Week Number]是别名列,您无法加入它?感谢你的帮助 - 请你能更具体地帮助我理解吗? – Jon295087

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 
+0

@Javlon_Ismatov非常感谢您的帮助。不幸的是,这并不适用于我,虽然我可能没有正确应用查询。我假设't2.BookedTime'指的是我的变量'Slot_Start_Date' - 是否正确?我相应地修改了所有'BookedTime'的实例,并且查询运行。但是,返回的结果不正确(当我对源数据进行交叉检查时)。此外,它不显示预订为零的周,结果集在第47周结束(我期待它显示到第52周) – Jon295087

+0

我修改了我的查询,希望它能起到帮助作用。对于永久性解决方案,您需要为日历年创建新表,它应该包含日期,年份,周数等,以获得更好的性能。 –