在 SQL 中的订单中的订单
Order by within an order by in SQL
我有点卡在按列排序。我从堆栈溢出中得到了另一个 的好答案,但现在只需要正确排序。
考虑一下我有这些结果(未排序)
|LloydA|20|
|LloydB|0 |
|LloydC|5 |
|JonesA|10|
|JonesB|0 |
|ZuberA|0 |
|ZuberB|10|
然后想先按第二列排序,然后再按第一列排序,所以结果是
|LloydA|20|
|LloydC|5 |
|LloydB|0 |
|JonesA|10|
|JonesB|0 |
|ZuberB|10|
|ZuberA|0 |
因为 20 是最大值,所以我想在顶部显示这一行,然后在它后面显示所有具有相同名称开头的行(即所有 Lloyd..)
我正在考虑使用 order by 进行子选择,但我正在努力。有没有人有什么提示。
这是一个生成您需要的结果的查询:
WITH
-- "t" contains the raw data
t(name, score) AS (
SELECT 'Lloyd0', 20 FROM DUAL UNION ALL
SELECT 'Lloyd1', 0 FROM DUAL UNION ALL
SELECT 'Lloyd2', 5 FROM DUAL UNION ALL
SELECT 'Jones0', 10 FROM DUAL UNION ALL
SELECT 'Jones1', 0 FROM DUAL UNION ALL
SELECT 'Zuber0', 0 FROM DUAL UNION ALL
SELECT 'Zuber1', 10 FROM DUAL
),
-- "u" generates the "name prefix" by removing the numbers form the names
u(name, score, name_prefix) AS (
SELECT name, score, regexp_replace(name, '\d+', '')
FROM t
),
-- "v" generates the max score per name_prefix ("group_rank") for each "group"
v(name, score, group_rank, name_prefix) AS (
SELECT name, score, MAX(score) OVER (PARTITION BY name_prefix), name_prefix
FROM u
)
SELECT name, score
FROM v
ORDER BY
-- Order by the group's rank first
group_rank DESC,
-- Order equally ranked groups by name
name_prefix ASC,
-- Order entries within each group by score
score DESC
当然,您不需要为此使用常见的 table 表达式。这可以通过派生的 table 或视图来完成,或者通过重复某些表达式来完成。
注意:您原来的问题是指 Lloyd0
而不是 LloydA
。不太清楚名称的 "interesting" 部分到底是什么(例如 Lloyd
),以及 "non-interesting" 部分是什么(例如 A
或 0
).但我怀疑这对答案来说并不重要。
根据你的 你不需要提取名称,你只需添加一个 GROUP MAX:
-- copied from the accepted answer
select p.* from people p
join (select p1.first_name, p1.last_name
from people p1 where p1.id = 17
)un
on un.first_name = p.first_name
where p.last_name like un.last_name || '%'
-- ADDED
order by -- find the MAX for each name
max(col2) over (partition by un.last_name),
last_name
我有点卡在按列排序。我从堆栈溢出中得到了另一个
考虑一下我有这些结果(未排序)
|LloydA|20|
|LloydB|0 |
|LloydC|5 |
|JonesA|10|
|JonesB|0 |
|ZuberA|0 |
|ZuberB|10|
然后想先按第二列排序,然后再按第一列排序,所以结果是
|LloydA|20|
|LloydC|5 |
|LloydB|0 |
|JonesA|10|
|JonesB|0 |
|ZuberB|10|
|ZuberA|0 |
因为 20 是最大值,所以我想在顶部显示这一行,然后在它后面显示所有具有相同名称开头的行(即所有 Lloyd..)
我正在考虑使用 order by 进行子选择,但我正在努力。有没有人有什么提示。
这是一个生成您需要的结果的查询:
WITH
-- "t" contains the raw data
t(name, score) AS (
SELECT 'Lloyd0', 20 FROM DUAL UNION ALL
SELECT 'Lloyd1', 0 FROM DUAL UNION ALL
SELECT 'Lloyd2', 5 FROM DUAL UNION ALL
SELECT 'Jones0', 10 FROM DUAL UNION ALL
SELECT 'Jones1', 0 FROM DUAL UNION ALL
SELECT 'Zuber0', 0 FROM DUAL UNION ALL
SELECT 'Zuber1', 10 FROM DUAL
),
-- "u" generates the "name prefix" by removing the numbers form the names
u(name, score, name_prefix) AS (
SELECT name, score, regexp_replace(name, '\d+', '')
FROM t
),
-- "v" generates the max score per name_prefix ("group_rank") for each "group"
v(name, score, group_rank, name_prefix) AS (
SELECT name, score, MAX(score) OVER (PARTITION BY name_prefix), name_prefix
FROM u
)
SELECT name, score
FROM v
ORDER BY
-- Order by the group's rank first
group_rank DESC,
-- Order equally ranked groups by name
name_prefix ASC,
-- Order entries within each group by score
score DESC
当然,您不需要为此使用常见的 table 表达式。这可以通过派生的 table 或视图来完成,或者通过重复某些表达式来完成。
注意:您原来的问题是指 Lloyd0
而不是 LloydA
。不太清楚名称的 "interesting" 部分到底是什么(例如 Lloyd
),以及 "non-interesting" 部分是什么(例如 A
或 0
).但我怀疑这对答案来说并不重要。
根据你的
-- copied from the accepted answer
select p.* from people p
join (select p1.first_name, p1.last_name
from people p1 where p1.id = 17
)un
on un.first_name = p.first_name
where p.last_name like un.last_name || '%'
-- ADDED
order by -- find the MAX for each name
max(col2) over (partition by un.last_name),
last_name