我返回并返回到此问题和答案。不幸的是,有几种情况下,使用“窗口函数进行排名”的迁移变得非常复杂。这两种情况是:
- 许多 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来解决问题。 –