【问题标题】:Pairing rows from two tables and show only content of first table if it does not exist in second table配对两个表中的行,如果第二个表中不存在,则仅显示第一个表的内容
【发布时间】:2020-09-22 13:08:23
【问题描述】:

这是this question 的后续行动,我从中得到了答案。

如果它们匹配,我仍在尝试将 2 个表中的记录配对。但是我现在需要查看第一个表中的记录,即使第二个记录不存在。

第一个表#T1 包含总是在第二个表#T2 中的事件之前出现的事件。但这一次,#T2 中的匹配事件可能永远不会出现。

第三个表 #E 包含为事件定义分别出现在 #T1 和 #T2 中的值的记录。

套用我上一个问题的答案:

逻辑如下 - 对于 T1 中的每一行 ...

  • 在 T2 中查找匹配的行,其中“匹配”表示 a) 相同的 VehicleId,b) 相同的 EventId,c) EventValue 受 #E 中的可能性限制,并且 d) 发生在 T1 中的事件之后
  • 从 T2 中为 T1 中的每一行查找第一个(最小)时间戳
  • 将 EventDelay 计算为两个时间戳之间的时间

现在最后一个要求是:

  • 如果 T2 中没有匹配的行,则只返回关于 T1 的数据。

这看起来就像使用 LEFT JOIN 而不是 INNER JOIN 一样简单,但它不起作用。

下面的新示例数据并尝试新查询仍返回 2 条记录而不是 3 条记录。

CREATE TABLE #T1 
(
    EventTimestamp DateTime, 
    VehicleId int, 
    EventId varchar(50), 
    EventValue varchar(50)
);

CREATE TABLE #T2 
(
    EventTimestamp DateTime, 
    VehicleId int, 
    EventId varchar(50), 
    EventValue varchar(50)
);

CREATE TABLE #E 
(
     EventId varchar(50), 
     FirstValue int, 
     LastValue varchar(50)
);

INSERT INTO #T1(EventTimestamp, VehicleId , EventId, EventValue)
VALUES (GETDATE(), 1, 'TwigStatus', '12'),
       (GETDATE(), 2, 'SafeProtectEvent', '5'),
       (DATEADD(minute, 10, GETDATE()), 1, 'TwigStatus', '12')

INSERT INTO #T2(EventTimestamp, VehicleId , EventId, EventValue)
VALUES (DATEADD(second, 30, GETDATE()), 1, 'TwigStatus', '7'),
       (DATEADD(second, 30, GETDATE()), 2, 'SafeProtectEvent', '6')

INSERT INTO #E(EventId, FirstValue, LastValue)
VALUES ('TwigStatus', '12', '7'),
       ('SafeProtectEvent', '5', '6')

; WITH ord AS
        (SELECT     t1.VehicleId, 
                    t1.EventTimestamp AS first, 
                    t2.EventTimestamp AS last,
                    t1.EventId, 
                    t2.EventValue,
                    ROW_NUMBER() OVER (PARTITION BY t1.VehicleId, t1.EventTimestamp, t1.EventId ORDER BY t1.EventTimestamp) AS rn
            FROM    #T1 AS t1
                    LEFT JOIN #T2 AS t2 ON t1.VehicleID = t2.VehicleID AND t1.EventID = t2.EventID
                    LEFT JOIN #E AS e ON t1.EventId = e.EventId 
                                      AND t1.EventValue = e.FirstValue
                                      AND t2.eventId = e.EventId 
                                      AND t2.EventValue = e.LastValue
            WHERE   t2.EventTimestamp > t1.EventTimestamp
        )

    SELECT      VehicleId, first, last, EventId, EventValue,
                DATEDIFF(second, first, last) AS EventDelay
        FROM    ord
        WHERE   rn = 1

DROP TABLE #E;
DROP TABLE #T1;
DROP TABLE #T2;

【问题讨论】:

  • 您的 CTE 的 where 子句引用了 left outer join 右侧的列,而不允许 null。这会将outer join 转换为inner join

标签: sql sql-server tsql subquery left-join


【解决方案1】:

您的 CTE 如下所示:

SELECT ...
FROM #t1 t1
LEFT JOIN #t2 t2 ON ...
LEFT JOIN #E  e  ON ...
WHERE t2.EventTimestamp > t1.EventTimestamp

where 子句中的条件移动到left joinon 子句中。否则,它将成为强制性的,并且在 t2 中没有匹配的行将被归档 - 因为它们的 EventTimestampnull,因此不满足不等式条件。

WITH ord AS
        (SELECT     t1.VehicleId, 
                    t1.EventTimestamp AS first, 
                    t2.EventTimestamp AS last,
                    t1.EventId, 
                    t2.EventValue,
                    ROW_NUMBER() OVER (PARTITION BY t1.VehicleId, t1.EventTimestamp, t1.EventId ORDER BY t1.EventTimestamp) AS rn
            FROM    #T1 AS t1
                    LEFT JOIN #T2 AS t2 ON t1.VehicleID = t2.VehicleID 
                                        AND t1.EventID = t2.EventID 
                                        AND t2.EventTimestamp > t1.EventTimestamp
                    LEFT JOIN #E AS e ON t1.EventId = e.EventId 
                                      AND t1.EventValue = e.FirstValue
                                      AND t2.eventId = e.EventId 
                                      AND t2.EventValue = e.LastValue
        )

    SELECT      VehicleId, first, last, EventId, EventValue,
                DATEDIFF(second, first, last) AS EventDelay
        FROM    ord
        WHERE   rn = 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 1970-01-01
    • 2021-11-27
    • 2018-04-24
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多