【发布时间】:2018-06-21 03:33:06
【问题描述】:
通过查看每行中的最大列值对查询进行排序的最有效方法是什么?
例如:
Dan | 5 | 0 | 3
Moe | 0 | 9 | 2
Joe | 3 | 3 | 8
排序此数据集应返回:Moe、Joe、Dan
我的数据集比上面的更复杂,所以我试图避免子查询与最大分组的任何组合。
【问题讨论】:
标签: sql sql-server tsql
通过查看每行中的最大列值对查询进行排序的最有效方法是什么?
例如:
Dan | 5 | 0 | 3
Moe | 0 | 9 | 2
Joe | 3 | 3 | 8
排序此数据集应返回:Moe、Joe、Dan
我的数据集比上面的更复杂,所以我试图避免子查询与最大分组的任何组合。
【问题讨论】:
标签: sql sql-server tsql
你可以使用CROSS APPLY:
SELECT *
FROM tab t
CROSS APPLY (SELECT MAX(col) c FROM (VALUES(t.col1),(t.col2),(t.col3)) sub(col)) s
ORDER BY s.c DESC;
输出:
┌──────┬──────┬──────┬──────┬───┐
│ name │ col1 │ col2 │ col3 │ c │
├──────┼──────┼──────┼──────┼───┤
│ Moe │ 0 │ 9 │ 2 │ 9 │
│ Joe │ 3 │ 3 │ 8 │ 8 │
│ Dan │ 5 │ 0 │ 3 │ 5 │
└──────┴──────┴──────┴──────┴───┘
很好的答案。我不认为有办法对任意数量的列(没有 dsql)执行此操作吗?
有一种不用动态SQL的方法:
SELECT DISTINCT t.*, c.s
FROM tab t
CROSS APPLY (VALUES(CAST((SELECT t.* for XML RAW) AS xml))) B(XMLData)
CROSS APPLY (SELECT MAX(a.value('.','INT') ) s
FROM B.XMLData.nodes('/row') AS C1(n)
CROSS APPLY C1.n.nodes('./@*') AS C2(a)
WHERE a.value('local-name(.)','varchar(100)') LIKE 'col%'
-- filtering based on name
-- it is also possible to JOIN and filter
-- based on metadata like sys.columns
) C
ORDER BY s DESC;
【讨论】:
CREATE VIEW my_view AS SELECT * FROM tab t CROSS APPLY (SELECT MAX(col) c FROM (VALUES(t.col1),(t.col2),(t.col3)) sub(col)) s 然后SELECT * FROM my_view ORDER BY c DESC?
我几乎从不对数据库进行排序。 在这种情况下,排序很复杂,而且比您提供的模型更复杂,我通常将数据从数据库中取出并在代码中进行排序。
当我这样做时,我总是会因为性能的提高而得到回报。 在内存中排序 8000000 行比在数据库中便宜得多。 由于您的数据模型很复杂,因此编写算法对其进行排序比编写 sql 更灵活 - 您可以编写能够抵抗架构更改的代码,并且将继续遵守您的规则。
【讨论】: