Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TSQL查询帮助返回缺少的行_Sql_Sql Server_Tsql - Fatal编程技术网

TSQL查询帮助返回缺少的行

TSQL查询帮助返回缺少的行,sql,sql-server,tsql,Sql,Sql Server,Tsql,需要以下内容的查询帮助 我有一个样本数据,如下表所示 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

需要以下内容的查询帮助 我有一个样本数据,如下表所示

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 

查询需要显示与时间序列相关的缺失行以及表行。缺少的行需要在表行之间交错。

您可以通过两个步骤执行此操作:使用交叉连接生成所有行,然后使用左连接输入值:

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的方法:


这里是另一种使用理货表的方法

首先,生成所有可能的放映时间,应该是00:00到23:00。然后获取每个电影ID的MINShowTime和MAXShowtime。现在对两个结果进行连接,以生成所有可能的电影ID和放映时间组合,使时间介于最小放映时间和最大放映时间之间

要获取Id,请使用交叉应用


如果您有SQL Server 2012或更高版本,则可以使用递归CTE并结合LEAD window函数,如下例所示:

    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

这种方法的主要优点是不需要额外的查找表

解决此问题的可能方法包括

临时表

自连接/交叉连接

a终止模式,以便将所有可能的显示时间存储在单独的表中,然后使用外部联接填充结果


我没有id列。如何确定不匹配行的id?您获得了CJ体验的代表;从我这里:
WITH CteHr(hr) AS(
    SELECT
        CAST(DATEADD(HOUR, hr, 0) AS TIME)
    FROM (VALUES
        (0), (1), (2), (3), (4), (5), (6), (7),
        (8), (9), (10), (11), (12), (13), (14), 
        (15), (16), (17), (18), (19), (20), (21), (22), (23)
    ) AS t(hr)
),
CteMinMax(MovieId, minHr, maxHr) AS(
    SELECT
        MovieId, MIN(Showtime), MAX(Showtime)
    FROM #MovieShows
    GROUP BY MovieId
)
SELECT
    t.Id,
    mm.MovieId,
    Showtime = h.hr
FROM CteMinMax mm
CROSS JOIN CteHr h
CROSS APPLY(
    SELECT TOP 1 Id
    FROM #MovieShows
    WHERE
        Movieid = mm.MovieId
        AND Showtime <= h.hr
    ORDER BY Showtime DESC
) t
WHERE h.hr BETWEEN mm.minHr  AND mm.maxHr
    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