需要以下查询帮助 我有一个示例数据,如下表所示。
Create table #MovieShows(Id int, Movieid varchar(20), Showtime time)
insert into #MovieShows values (11,'m1','13:00')
insert into #MovieShows values (23,'m2','14:00')
insert into #MovieShows values (34,'m1','15:00')
insert into #MovieShows values (45,'m2','16:00')
insert into #MovieShows values (55,'m2','20:00')
insert into #MovieShows values (64,'m1','16:00')
insert into #MovieShows values (66,'m2','21:00')
insert into #MovieShows values (81,'m1','20:00')
go
select * from #MovieShows order by Movieid, id
==========================
Need a query to show the missing rows along with table rows.
Desired output should be
Id MovieID Showtime
11 m1 13:00
11 m1 14:00 --New row
34 m1 15:00
64 m1 16:00
64 m1 17:00 --New row
64 m1 18:00 --New row
64 m1 19:00 --New row
81 m1 20:00
23 m2 14:00
23 m2 15:00 --New row
45 m2 16:00
45 m2 17:00 --New row
45 m2 18:00 --New row
45 m2 19:00 --New row
55 m2 20:00
66 m2 21:00
查询需要显示与时间序列相关的缺失行以及表行。丢失的行需要在表行之间进行交错。
答案 0 :(得分:2)
您可以分两步执行此操作:使用cross join
生成所有行,然后left join
放入值:
select m.moveid, s.showtime
from (select distinct movieid from movieshows) m cross join
(select distinct showtime from movieshows) t left join
movieshows ms
on ms.movieid = m.movieid and ms.showtime = t.showtime;
我唯一不明白的是id
。如何确定不匹配行的id
?
嗯,这是获取id
的一种方式:
select ms.id, m.moveid, s.showtime
from (select distinct movieid from movieshows) m cross join
(select distinct showtime from movieshows) t outer apply
(select top 1 ms.*
from movieshows ms
where ms.movieid = m.movieid and ms.showtime <= t.showtime
order by ms.showtime desc
) ms
答案 1 :(得分:0)
这是使用Tally Table的另一种方法。
首先,生成所有可能的ShowTime
,其应为00:00
到23:00
。然后获取每个MIN(ShowTime)
的{{1}}和MAX(Showtime)
。现在对两个结果执行MovieId
以生成JOIN
和MovieId
的所有可能组合,以便时间介于Showtime
和MIN
{{之间1}}。
要获取MAX
,请使用Showtime
Id
答案 2 :(得分:0)
如果你有SQL Server 2012或更高版本,你可以使用递归CTE结合LEAD窗口函数,如下例所示:
DECLARE @MovieShows TABLE
(
Id INT, Movieid VARCHAR(20), Showtime TIME
PRIMARY KEY (Movieid, Showtime)
)
INSERT INTO @MovieShows
SELECT 11,'m1','13:00' UNION ALL
SELECT 34,'m1','15:00' UNION ALL
SELECT 64,'m1','16:00' UNION ALL
SELECT 81,'m1','21:00' UNION ALL
SELECT 23,'m2','14:00' UNION ALL
SELECT 45,'m2','16:00' UNION ALL
SELECT 55,'m2','20:00' UNION ALL
SELECT 66,'m2','21:00'
;WITH CTE_Shows
AS
(
SELECT Id
,Movieid
,Showtime
,LEAD(Showtime, 1, NULL) OVER (PARTITION BY Movieid ORDER BY Showtime) AS NextShowTime
FROM @MovieShows MovesBase
UNION ALL -- Fill in the gaps by performing a recursive union
SELECT Id
,Movieid
,DATEADD(HOUR, 1, Showtime) AS Showtime -- Add one hour to the current show time.
,Fill.NextShowTime
FROM CTE_Shows Fill
WHERE DATEADD(HOUR, 1, Fill.Showtime) < Fill.NextShowTime -- Only perform recursive union where the current show time + 1 hour is less than the next show time in the current dataset.
)
SELECT Id
,Movieid
,Showtime
FROM CTE_Shows
ORDER BY Movieid, Showtime
此方法的主要优点是无需额外的查找表。
答案 3 :(得分:0)
解决此问题的可能方法包括
临时表
自/交叉联接
修改架构,以便将所有可能的放映时间存储在单独的表中,然后使用外部联接填充结果。