Я пытаюсь включить ROW_NUMBER с ORDER BY, но он не работает должным образом. Я попытался использовать ORDER BY (без ROW_NUMBER), и результаты с и без ORDER BY отличаются (даже количество строк отличается).
Вот полный запрос (я знаю, что это не лучший запрос):
WITH cte1
AS
(
SELECT t1.OrderNo, t1.BlockID, t1.PcbID AS 'TopPcbID', t3.PcbID AS 'MountedOn',
t3.TimeDone AS TimeEnd, t9.TimeDone, t7.McID, t8.DeviceID, t8.Program, t6.CurMcID, t9.DeviceID AS D1, t9.Program AS P1,
ROW_NUMBER() OVER(PARTITION BY t3.PcbID, t7.McID ORDER BY t9.TimeDone DESC) RN
FROM PanelBlockTrace t1
INNER JOIN (SELECT PcbID, MIN(BlockNo) AS 'MINIM' FROM PanelBlockTrace
GROUP BY PcbID) t2 ON t1.PcbID = t2.PcbID
INNER JOIN PcbTrace t3 ON t1.PcbID = t3.PcbID OR
(CASE WHEN t1.BlockNo = 0 THEN t1.BlockID ELSE t1.PcbID END) = t3.PcbID
INNER JOIN (SELECT PcbID, MAX(McID) AS 'MAXIM' FROM PcbTrace
WHERE Program NOT LIKE 'PANEL%' GROUP BY PcbID) t4 ON t3.PcbID = t4.PcbID
INNER JOIN LineDesc t5 ON t3.McID = t5.McID
INNER JOIN (SELECT LineID, MAX(McID) AS 'CurMcID' FROM LineDesc WHERE McID NOT LIKE '%9' GROUP BY LineID) t6 ON t5.LineID = t6.LineID
INNER JOIN LineDesc t7 ON t5.LineID = t7.LineID
LEFT JOIN PcbTrace t8 ON t3.PcbID = t8.PcbID AND t7.McID = t8.McID
LEFT JOIN PcbTrace t9 ON t8.DeviceID IS NULL
AND t9.TimeDone BETWEEN DATEADD(DAY,-1,CONVERT(date, t3.TimeDone)) AND t3.TimeDone
AND t9.McID = CurMcID AND t9.McID = t7.McID
WHERE (t1.BlockID IN (...) OR t1.PcbID IN (...))
AND t1.BlockNo = t2.MINIM
AND t1.BlockID != t1.PcbID
AND t1.PcbID != ''
AND t3.Program NOT LIKE 'PANEL%'
AND t3.McID = t4.MAXIM
),
cte11
AS
(
SELECT * FROM cte1
WHERE RN <= 3
),
cte12
AS
(
SELECT t1.OrderNo, t1.BlockID, t1.TopPcbID, t1.MountedOn, t1.TimeEnd, LEAD(t1.TimeDone,2) OVER(ORDER BY t1.MountedOn) AS T1,
t1.McID, t1.DeviceID, t1.Program, t1.D1, t1.P1, t2.CurMcID, t1.RN
FROM cte11 t1
INNER JOIN
(SELECT t1.MountedOn,t1.McID,t1.P1,t1.Program,MAX(RN) AS LastRec, t1.CurMcID-1 AS CurMcID
FROM cte11 t1
LEFT JOIN (SELECT MountedOn,McID,Program,P1 FROM cte11 WHERE RN = 1) t2 ON
t1.MountedOn = t2.MountedOn AND t1.McID = t2.McID AND (t1.Program = t2.Program OR t1.P1 = t2.P1)
WHERE RN <= 3
GROUP BY t1.MountedOn, t1.McID, t1.P1, t1.Program, t1.CurMcID) t2 ON
t1.MountedOn = t2.MountedOn AND t1.McID = t2.McID
AND (t1.RN = t2.LastRec OR t1.RN = 1)
),
cte2
AS
(
SELECT t1.*,t2.DeviceID AS D2, t2.Program AS P2, t2.TimeDone AS T2
FROM cte12 t1
LEFT JOIN PcbTrace t2 ON t1.DeviceID IS NULL AND t1.D1 IS NULL AND t1.McID = t1.CurMcID AND t1.McID = t2.McID
AND t2.TimeDone BETWEEN DATEADD(DAY,-1,CONVERT(date, t1.T1)) AND t1.T1
)
SELECT * FROM cte2
Во всяком случае, здесь все становится странным.
Конечная цель - включить ROW_NUMBER:
cte2
AS
(
SELECT t1.*,t2.DeviceID AS D2, t2.Program AS P2, t2.TimeDone AS T2,
ROW_NUMBER() OVER (PARTITION BY MountedOn, t1.McID ORDER BY t2.TimeDone) RN2
FROM cte12 t1
LEFT JOIN PcbTrace t2 ON t1.DeviceID IS NULL AND t1.D1 IS NULL AND t1.McID = t1.CurMcID AND t1.McID = t2.McID
AND t2.TimeDone BETWEEN DATEADD(DAY,-1,CONVERT(date, t1.T1)) AND t1.T1
)
SELECT * FROM cte2
Поскольку добавление ROW_NUMBER приводит к совершенно другому результату (без ROW_NUMBER: 3762 строки, с ROW_NUMBER: 17 строк), я попытался упростить последнюю часть и понял, что причиной является ORDER BY.
cte2
AS
(
SELECT t2.DeviceID AS Device2, t2.Program AS Program2, t2.TimeDone AS Time2
FROM cte12 t1
LEFT JOIN PcbTrace t2 ON t1.DeviceID IS NULL AND t1.D1 IS NULL AND t1.McID = t1.CurMcID AND t1.McID = t2.McID
AND t2.TimeDone BETWEEN DATEADD(DAY,-1,CONVERT(date, t1.T1)) AND t1.T1
)
SELECT * FROM cte2
Результат без ORDER BY (первые 10 из 3762 строк):
Device2 Program2 Time2
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
1557852877 G8542G004MPB_4M3_00 2019-05-15 00:01:59.777
1557852877 G8542G004MPB_4M3_00 2019-05-15 00:04:56.790
1557852877 G8542G004MPB_4M3_00 2019-05-15 00:05:42.843
Код с ЗАКАЗАТЬ ПО:
cte2
AS
(
SELECT t2.DeviceID AS Device2, t2.Program AS Program2, t2.TimeDone AS Time2
FROM cte12 t1
LEFT JOIN PcbTrace t2 ON t1.DeviceID IS NULL AND t1.D1 IS NULL AND t1.McID = t1.CurMcID AND t1.McID = t2.McID
AND t2.TimeDone BETWEEN DATEADD(DAY,-1,CONVERT(date, t1.T1)) AND t1.T1
)
SELECT * FROM cte2
ORDER BY Time2
Результат (первые 10 из 17 строк):
Device2 Program2 Time2
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
NULL NULL NULL
Примечание:
- Этот cte является фактически четвертым cte и использует результат другого cte (cte12). Я не уверен, как это может повлиять на результат.
- Там нет ddl, потому что я извлекаю данные из существующей базы данных, и будет слишком сложно моделировать такое количество таблиц.
- И да, единственное различие между двумя последними запросами - это предложение ORDER BY, но количество возвращаемых строк отличается (3762 против 17)
Редактировать:
- Если я просто использую TOP (скажем, TOP 10000), результат будет, как и ожидалось, 3762 строк. Но если число TOP слишком велико (что-либо больше, чем TOP 27415), оно вернется к 17 строкам
Каким-то образом это работает как ожидалось (3762 строки), если я изменяю временные ограничения с
t2.TimeDone МЕЖДУ DATEADD (ДЕНЬ, -1, КОНВЕРТ (дата, t1.T1)) И t1.T1
до
t2.TimeDone МЕЖДУ DATEADD (ДЕНЬ, -1, t1.T1) И t1.T1