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
我正在尝试 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