SQL 服务器同行连接使用 rownum returns 无值

SQL Server same-row joins using rownum returns no values

我正在尝试 return 同一行中的多个记录值,因此我想对同一个 table 使用多个连接。我需要并排显示前两条记录。这些联接变为 'LatestNote' 和 'SecondLatestNote',使用 RowNumber 将它们分开。

下面是一个非常简单的例子,但我没有得到任何结果。我在这里搞砸了什么?

SQL 具有 return 没有值的联接:

DECLARE @DateFrom AS DATETIME = CONVERT(DateTime, '2017-01-01 00:00:00.000', 120)
DECLARE @DateTo AS DATETIME = CONVERT(DateTime, '2018-01-01 00:00:00.000', 120)

SELECT
    LatestNote.NoteCode,
    LatestNote.NoteDate,           
    SecondLatestNote.NoteCode AS [NoteCode2nd],
    SecondLatestNote.NoteDate AS [NotDate2nd]

FROM Locations LOC


LEFT JOIN (
            SELECT TOP 2 LocationID, NoteID, Row_Number() OVER (ORDER BY Notedate DESC) AS RowNum
            FROM Notes(nolock) 
            WHERE NoteCode = 'NOTIFY' 
            AND NoteDate BETWEEN @DateFrom AND @DateTo
            ) 
                AS TopTwoNotes ON TopTwoNotes.LocationID = LOC.LocationID 

                LEFT JOIN Notes AS LatestNote ON LatestNote.NoteID = TopTwoNotes.NoteID AND TopTwoNotes.RowNum = 1

                LEFT JOIN Notes AS SecondLatestNote ON SecondLatestNote.NoteID = TopTwoNotes.NoteID AND TopTwoNotes.RowNum = 2 

WHERE LOC.LocationID = 308644

结果全为 NULL,只有一行被 returned,因为我使用的是 LEFT JOIN。为什么这不起作用??

这 SQL 表明数据在那里,结果如下:

SELECT TOP 2 LocationID, NoteID, Row_Number() OVER (ORDER BY NoteDate DESC) AS RowNum
            FROM Notes(nolock) 
            WHERE NoteCode = 'NOTIFY' 
            AND NoteDate BETWEEN @DateFrom AND @DateTo
            AND LocationID = 308644 

LocationID  NoteID  RowNum
308644  10291348    1
308644  10130566    2


SELECT
    NoteID,
    NoteCode,
    NoteDate,
    LEN(CAST(Note AS VARCHAR(8000))) AS [NoteCharCount]
FROM
    Notes
WHERE
    LocationID = 308644
    AND NoteDate BETWEEN @DateFrom AND @DateTo


NoteID  NoteCode    NoteDate    NoteCharCount
10130566    NOTIFY  2017-11-08  50
10291348    NOTIFY  2017-12-13  66

我一定是遗漏了什么 - 我不能像这样使用 rownum 加入吗?

感谢您的帮助。

你需要在子查询的where子句中添加条件LocationID = 308644,否则第一行和第二行可能不包含LocationID = 308644

然后你使用 LEFT JOIN 将不匹配 LocationID = 308644 所以将是 NULL 行。

SELECT LatestNote.notecode, 
       LatestNote.notedate, 
       SecondLatestNote.notecode AS [NoteCode2nd], 
       SecondLatestNote.notedate AS [NotDate2nd] 
FROM   locations LOC 
       LEFT JOIN (SELECT TOP 2 locationid, 
                               noteid, 
                               Row_number() 
                                 OVER ( 
                                   ORDER BY notedate DESC) AS RowNum 
                  FROM   notes(nolock) 
                  WHERE  notecode = 'NOTIFY' 
                         AND notedate BETWEEN @DateFrom AND @DateTo AND LocationID = 308644) AS TopTwoNotes 
              ON TopTwoNotes.locationid = LOC.locationid 
       LEFT JOIN notes AS LatestNote 
              ON LatestNote.noteid = TopTwoNotes.noteid 
                 AND TopTwoNotes.rownum = 1 
       LEFT JOIN notes AS SecondLatestNote 
              ON SecondLatestNote.noteid = TopTwoNotes.noteid 
                 AND TopTwoNotes.rownum = 2 
WHERE  LOC.locationid = 308644 

编辑

你可以让 locations table LEFT JOIN 在子查询上。

SELECT LatestNote.notecode, 
       LatestNote.notedate, 
       SecondLatestNote.notecode AS [NoteCode2nd], 
       SecondLatestNote.notedate AS [NotDate2nd] 
FROM   (
        SELECT TOP 2 TopTwoNotes.locationid, 
                     TopTwoNotes.noteid, 
                     Row_number() 
                       OVER (ORDER BY TopTwoNotes.notedate DESC) AS RowNum 
        FROM   locations LOC 
               LEFT JOIN notes(nolock) TopTwoNotes
                       ON TopTwoNotes.locationid = LOC.locationid 
        WHERE  TopTwoNotes.notecode = 'NOTIFY' 
               AND TopTwoNotes.notedate BETWEEN @DateFrom AND @DateTo 
               AND LOC.locationid = 308644
        ORDER BY TopTwoNotes.notedate DESC
        ) AS TopTwoNotes 
       INNER JOIN notes AS LatestNote 
               ON LatestNote.noteid = TopTwoNotes.noteid 
                  AND TopTwoNotes.rownum = 1 
       INNER JOIN notes AS SecondLatestNote 
               ON SecondLatestNote.noteid = TopTwoNotes.noteid 
                  AND TopTwoNotes.rownum = 2 

你可以用apply解决这个问题:

SELECT n_latest.NoteCode, n_latest.NoteDate,           
       n_prev.NoteCode AS NoteCode2nd, n_prev.NoteDate AS NoteDate2nd
FROM Locations l OUTER APPLY
     (SELECT n.*
      FROM Notes n
      WHERE n.NoteCode = 'NOTIFY' AND
            n.NoteDate BETWEEN @DateFrom AND @DateTo
      ORDER BY n.NoteDate DESC
      OFFSET 0 ROWS FETCH FIRST 1 ROW ONLY
     ) n_latest OUTER APPLY
     (SELECT n.*
      FROM Notes n
      WHERE n.NoteCode = 'NOTIFY' AND
            n.NoteDate BETWEEN @DateFrom AND @DateTo
      ORDER BY n.NoteDate DESC
      OFFSET 1 ROWS FETCH FIRST 1 ROW ONLY
     ) n_prev