如何阻止SQL连接两次处理一行

Phi*_* O. 6 sql join

首先让我说我知道我的主题不完全正确,但我不知道该怎么说.

我告诉你:而不是试图解释我想要做什么.

下面是我的表中相关数据的片段(我使用CONVERT将日期/时间字段修剪为我们需要的值.所有日期都是"XX/XX/XXXX 00:00:00.000",所有时间都是"01/01/1900 XX:XX:XX.000"其中XX是真值,00是占位符).

CALLNBR     DATE       START      END
----------- ---------- ---------- ----------
0000182867  03/07/2012 10:55:00   12:20:00
0000182867  03/07/2012 12:20:00   13:00:00
0000182779  03/06/2012 14:29:00   15:03:00
0000182749  03/06/2012 15:15:00   15:30:00
0000182748  03/07/2012 10:40:00   12:30:00
0000182748  03/07/2012 12:30:00   13:20:00
0000182740  03/06/2012 11:00:00   11:30:00
0000182740  03/06/2012 11:30:00   12:00:00
0000182735  03/07/2012 09:10:00   10:00:00
0000182735  03/07/2012 10:00:00   10:40:00
0000182735  03/06/2012 14:40:00   15:10:00
0000182735  03/06/2012 15:10:00   15:30:00
0000182735  03/06/2012 15:30:00   16:45:00
Run Code Online (Sandbox Code Playgroud)

我需要将时间串在一起,其中一个记录结束时间是下一个的开始时间.我想得到一个类似的结果(由CALLNBR 182735过滤):

CallNbr     DATE       t1Start    t1end      t2Start    t2end      t3Start    t3end
----------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
0000182735  03/06/2012 14:40:00   15:10:00   15:10:00   15:30:00   15:30:00   16:45:00
0000182735  03/07/2012 09:10:00   10:00:00   10:00:00   10:40:00   NULL       NULL
Run Code Online (Sandbox Code Playgroud)

但我得到的结果是:

CallNbr     DATE       t1Start    t1end      t2Start    t2end      t3Start    t3end
----------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
0000182735  03/06/2012 14:40:00   15:10:00   15:10:00   15:30:00   15:30:00   16:45:00
0000182735  03/06/2012 15:10:00   15:30:00   15:30:00   16:45:00   NULL       NULL
0000182735  03/07/2012 09:10:00   10:00:00   10:00:00   10:40:00   NULL       NULL
Run Code Online (Sandbox Code Playgroud)

我的问题是中间记录,其值在返回的第一条记录中:

0000182735  03/06/2012 15:10:00   15:30:00   15:30:00   16:45:00   NULL       NULL
Run Code Online (Sandbox Code Playgroud)

不幸的是,我无法通过t3Start或t3End来压制NULLS,因为这会消除(在本例中)03/07/2012的记录.

0000182735  03/07/2012 09:10:00   10:00:00   10:00:00   10:40:00   NULL       NULL
Run Code Online (Sandbox Code Playgroud)

现在对于SELECT(为了使它更具可读性,我正在剥离我的CONVERT'ers):

    SELECT
      t1.CallNbr,
      t1.STRTDATE,
      t1.strttime as t1Start,
      t1.endtme   as t1end,
      t2.strttime as t2Start,
      t2.endtme   as t2end,
      t3.strttime as t3Start,
      t3.endtme as t3end
    FROM       TableA t1
    INNER JOIN TableA t2 ON t1.endtme    = t2.strttime
                        AND t1.strtdate  = t2.strtdate
                        AND t1.CALLNBR   = t2.CALLNBR
                        AND t1.LINITMTYP = 'L' 
    LEFT  JOIN TableA t3 ON t3.CALLNBR  = t2.CALLNBR
                        AND t3.strttime = t2.endtme
                        AND t3.strtdate = t1.strtdate
    WHERE t1.CALLNBR = '0000182735'
    ORDER BY t1.CALLNBR, t1.strtdate
Run Code Online (Sandbox Code Playgroud)

即使你无法帮忙,也要感谢你花时间阅读它.

谢谢,

菲利普

Jus*_*ony 1

如果您能够使用 ROW_NUMBER() 功能,那么我将执行以下操作。这可确保查询仅从开头拉取,而不是从中间拉取。您可以通过这种方式稍微清理一下查询,但我不确定。您需要的只是 RowNum = 1,但是您可以使用我在注释中添加的父表 rownum > 子表 rownum 添加额外的安全性,不允许任何重叠

SELECT t1.CallNbr, t1.StrtDate, t1.StrtTime, t1.EndTime, t1.LINITMTYP,
    ROW_NUMBER() OVER (PARTITION BY t1.CALLNBR, t1.strtdate ORDER BY t1.StrtTime) AS RowNum
INTO #MyTemp
FROM TableA AS t1

SELECT
      t1.CallNbr,
      t1.STRTDATE,
      t1.strttime as t1Start,
      t1.endtme as t1end,
      t2.strttime as t2Start,
      t2.endtme as t2end,
      t3.strttime as t3Start,
      t3.endtme as t3end
    FROM #MyTemp t1
        JOIN #MyTemp t2 ON t1.endtme    = t2.strttime
                  AND t1.strtdate  = t2.strtdate
                  AND t1.CALLNBR   = t2.CALLNBR
                  AND t1.LINITMTYP = 'L' 
                  --You could add extra security using the following
                  --AND t2.RowNum > t1.RowNum
    LEFT JOIN #MyTemp t3 ON t3.CALLNBR  = t2.CALLNBR
                       AND t3.strttime = t2.endtme
                       AND t3.strtdate = t1.strtdate
                       --You could add extra security using the following
                       --AND t3.RowNum > t2.RowNum
    WHERE t1.CALLNBR = '0000182735' 
        AND t1.RowNum = 1
    ORDER BY t1.CALLNBR, t1.strtdate
Run Code Online (Sandbox Code Playgroud)