我返回並返回到此問題和答案。不幸的是,有幾種情況下,使用「窗口函數進行排名」的遷移變得非常複雜。這兩種情況是:
- 許多 Oracle查詢的選擇部分保DENSE_RANK結構基於不同的順序進行分組套/彙總
- 分組
因此,我會添加到答案附加信息。 原始數據SQLFIDDLE:http://sqlfiddle.com/#!6/e5c6d/6
閱讀Oracle函數:
select max(m.id), m.someId keep (DENSE_RANK FIRST ORDER BY m.UpdateDate desc)
from MyTable m
groupBy m.someId
有我們的組中選擇m.id的最大值(someId,UpdateDate),其中UpdateDate是它最大的組(someId )
2.直接的方式不起作用,因爲錯誤的:列「MyTable.UpdateDate」是在選擇無效列表,因爲它不包含在聚合函數或GROUP BY子句中。
SELECT FIRST_VALUE(id) OVER(PARTITION BY someId ORDER BY UpdateDate DESC, id DESC) first_in_orderedset , someId
FROM MyTable
GROUP BY someId
3. improoved '直線前進' 是無效藥
SELECT someId, MIN(first_in_orderedset)
FROM
(SELECT FIRST_VALUE(id) OVER(PARTITION BY someId ORDER BY UpdateDate DESC, id DESC) first_in_orderedset , someId
FROM MyTable) t
GROUP BY someId;
4。交叉應用:
SELECT grouped.someId, orderedSet.FirstUpdateDate, maxInSet.first_in_orderedset FROM
(
SELECT mt.someId
FROM MyTable mt
GROUP BY mt.someId
) grouped CROSS APPLY
(
SELECT top 1 mt2.UpdateDate as FirstUpdateDate
FROM MyTable mt2
WHERE mt2.someId=grouped.someId
ORDER BY UpdateDate desc
) orderedSet CROSS APPLY
(
SELECT max(mt3.id) as first_in_orderedset
FROM MyTable mt3
WHERE mt3.someId=grouped.someId and mt3.UpdateDate=orderedSet.FirstUpdateDate
) maxInSet;
5.現在讓我們得到更復雜的表格和更復雜的查詢: ORACLE:http://sqlfiddle.com/#!4/c943c/23 SQL SERVER:http://sqlfiddle.com/#!6/dc7fb/1/0 (數據預生成的,它是在這兩個沙箱是相同的 - 很容易比較的結果) 表:
CREATE TABLE AlarmReports (
id int PRIMARY KEY,
clientId int, businessAreaId int , projectId int, taskId int,
process1Spent int, process1Lag int, process1AlarmRate varchar2(1) null,
process2Spent int, process2Lag int, process2AlarmRate varchar2(1) null,
process3Spent int, process3Lag int, process3AlarmRate varchar2(1) null
)
Oracle查詢:
SELECT clientId, businessAreaId, projectId,
sum(process1Spent),
sum(process2Spent),
sum(process3Spent),
MIN(process1AlarmRate) KEEP (DENSE_RANK FIRST ORDER BY process1Lag DESC),
MIN(process2AlarmRate) KEEP (DENSE_RANK FIRST ORDER BY process2Lag DESC),
MIN(process3AlarmRate) KEEP (DENSE_RANK FIRST ORDER BY process3Lag DESC)
FROM AlarmReports
GROUP BY GROUPING SETS ((),(clientId),(clientId, projectId),(businessAreaId),(clientId,businessAreaId))
SQL查詢:
(to be continued)
居然還有我已經計劃把用C#wroted我的自定義聚合。如果有人感興趣,請與我聯繫...自定義聚合是這類問題的最佳解決方案,但它在varchar長度方面不是非常明顯的。對於每個varchar長度,您都有義務創建「專用」聚合函數
我不知道它..它應該如何工作,沒有'someId組'?我的查詢總是會返回3個條目,因爲我在表中有3個不同的someIds。你的查詢將返回不依賴於不同someIds數量的結果,所以它應該是錯誤的呢? – javagirl
@javagirl - 你先試了嗎?它會起作用。至於它是如何工作的,分析函數('OVER()...')可以有一個'PARTITION BY',並且不需要在整個級別上進行分組。它爲表中的每一行返回一個值。 – Lamak
我誤解了原始數據。通過將someid放入分區而不是id來解決問題。 –