SQL Server:仅使用Join / Cross Apply中的记录一次

时间:2017-10-12 11:54:13

标签: sql sql-server

我希望我的Cross Apply删除记录,如果它已加入,而不是考虑加入其他记录。是否有可能在一个声明中这样做?

因此,在下面的示例中,期望的结果是第二条记录的MatchID = 1,因为第一条记录已经采用了B.recordID = 2。我相信示例代码会说清楚:

http://sqlfiddle.com/#!6/555a1/5/0

总而言之,我需要表B中的记录,如果它们被用作匹配则不再被视为可用。

EDIT1:添加示例代码:

构建架构:

CREATE TABLE A 
(
    id int,
    eventName varchar(80),
    startdateTime datetime,
    duration int,
    MatchedID int NULL
)

CREATE TABLE B 
(
    id int,
    eventName varchar(80),
    startdateTime datetime,
    duration int
)

INSERT INTO A
    SELECT 1, 'e1', dateadd(day, -1, getdate()), 5, NULL
    UNION 
    SELECT 2, 'e1', dateadd(hour, -1, getdate()), 5, NULL

INSERT INTO B
    SELECT 1, 'e1', dateadd(day, -1, getdate()), 4
    UNION 
    SELECT 2, 'e1', dateadd(hour, -1, getdate()), 5

查询:

UPDATE toUpdate
SET toUpdate.MatchedID = Tbtmp.id
FROM A toUpdate
CROSS APPLY (SELECT TOP(1) *
             FROM B WHERE toUpdate.eventName = B.eventName
             ORDER BY ABS(toUpdate.Duration - B.Duration)) Tbtmp;

SELECT * FROM A

结果:

| id | eventName |            startdateTime | duration | MatchedID |
+----+-----------+--------------------------+----------+-----------+
|  1 |        e1 | 2017-10-11T11:34:15.083Z |        5 |         2 |
|  2 |        e1 | 2017-10-12T10:34:15.083Z |        5 |         2 |

预期结果(第二条记录的MatchedID应为1,因为即使距离原始记录更近,也已使用2)

| id | eventName |            startdateTime | duration | MatchedID |
+----+-----------+--------------------------+----------+-----------+
|  1 |        e1 | 2017-10-11T11:34:15.083Z |        5 |         2 |
|  2 |        e1 | 2017-10-12T10:34:15.083Z |        5 |         1 |

1 个答案:

答案 0 :(得分:1)

你可以尝试一下吗?为了删除重复记录(因为eventName连接)我使用额外的CTE。我用你的样本数据测试了它,看起来很有效。我希望它也适用于你的真实数据。

;WITH toUpdate AS
(
    SELECT *, 
        RN_Update = ROW_NUMBER() OVER(PARTITION BY A.eventName ORDER BY A.id) 
    FROM A
)
, fromSource AS
(
    SELECT B.*,
        A.RN_Update, 
        RN_Source = ROW_NUMBER() OVER(PARTITION BY A.eventName, A.id ORDER BY A.id, ABS(A.Duration - B.Duration)) 
    FROM B
        INNER JOIN toUpdate A ON A.eventName = B.eventName 
)
UPDATE toUpdate 
SET
    MatchedID = fromSource.id
FROM toUpdate
    INNER JOIN fromSource ON toUpdate.eventName = fromSource.eventName
                AND toUpdate.RN_Update = fromSource.RN_Source
                AND fromSource.RN_Update = fromSource.RN_Source

结果:

id          eventName   startdateTime           duration    MatchedID
----------- ----------- ----------------------- ----------- -----------
1           e1          2017-10-11 15:33:11.890 5           2
2           e1          2017-10-12 14:33:11.890 5           1