sql ORDER BY 按特定顺序排列多个值?
Posted
技术标签:
【中文标题】sql ORDER BY 按特定顺序排列多个值?【英文标题】:sql ORDER BY multiple values in specific order? 【发布时间】:2011-09-13 23:50:27 【问题描述】:好的,我有一个带有索引键和非索引字段的表。 我需要找到具有特定值的所有记录并返回该行。 我想知道我是否可以按多个值排序。
例子:
id x_field
-- -----
123 a
124 a
125 a
126 b
127 f
128 b
129 a
130 x
131 x
132 b
133 p
134 p
135 i
伪:希望结果像这样排序,where ORDER BY x_field = 'f', 'p', 'i', 'a'
SELECT *
FROM table
WHERE id NOT IN (126)
ORDER BY x_field 'f', 'p', 'i', 'a'
所以结果是:
id x_field
-- -----
127 f
133 p
134 p
135 i
123 a
124 a
125 a
129 a
语法是有效的,但是当我执行查询时它永远不会返回任何结果,即使我将它限制为 1 条记录。有没有其他方法可以解决这个问题?
将 x_field 视为测试结果,我需要验证所有符合条件的记录。我想按失败值、通过值对测试结果进行排序。所以我可以先验证失败的值,然后使用 ORDER BY 验证传递的值。
我不能做什么:
GROUP BY,因为我需要返回具体的记录值 WHERE x_field IN('f', 'p', 'i', 'a'),我需要所有值,因为我试图将一个查询用于多个验证测试。并且 x_field 值不是 DESC/ASC 顺序写完这个问题后,我开始认为我需要重新考虑这个问题,哈哈!
【问题讨论】:
也许是工会?按照您希望返回结果的顺序构建单独的查询,然后合并这些查询? 【参考方案1】:...
WHERE
x_field IN ('f', 'p', 'i', 'a') ...
ORDER BY
CASE x_field
WHEN 'f' THEN 1
WHEN 'p' THEN 2
WHEN 'i' THEN 3
WHEN 'a' THEN 4
ELSE 5 --needed only is no IN clause above. eg when = 'b'
END, id
【讨论】:
【参考方案2】:试试:
ORDER BY x_field='f', x_field='p', x_field='i', x_field='a'
您在正确的轨道上,但是通过仅将 x_field 放在 'f' 值上,其他三个被视为常量,而不是与数据集。
【讨论】:
Postgres 是否支持隐式布尔值?如果是,布尔值如何排序? 我喜欢这个解决方案,但它没有再返回任何东西。 @gbn,是的和错误的您可以使用带有“VALUES ('f',1),('p',2),('a',3),('i',4)" 的 LEFT JOIN 并使用第二列在您的 order-by 表达式中。 Postgres 将使用 Hash Join,如果你有很多值,它会比一个巨大的 CASE 快得多。而且更容易自动生成。
如果这个排序信息是固定的,那么它应该有自己的表。
【讨论】:
这是迄今为止最优雅的解决方案! 如果有人需要使用建议方法的完整查询,我添加了它here。【参考方案4】:我为此找到了一个更清洁的解决方案:
ORDER BY array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field)
注意:array_position 需要 Postgres v9.5 或更高版本。
【讨论】:
需要注意的是,array_position() 仅在 Postgres v9.5 及更高版本中可用,afaik。 谢谢,比起 CASE 方法更喜欢这个。也适用于整数;array_position(ARRAY[1, 0]::integer[], x_field)
【参考方案5】:
使用case
开关将代码转换为可排序的数字:
ORDER BY
case x_field
when 'f' then 1
when 'p' then 2
when 'i' then 3
when 'a' then 4
else 5
end
【讨论】:
【参考方案6】:CASE
和 ORDER BY
建议应该都可以,但我要建议一匹不同颜色的马。假设 x_field
只有合理数量的值,并且您已经知道它们是什么,请创建一个 enumerated type,并将 F、P、A 和 I 作为值(加上任何其他可能的值)。枚举将按照 CREATE
语句所暗示的顺序排序。此外,您可以使用有意义的值名称(您的实际应用程序可能会这样做,而您只是为了保密而将它们屏蔽了)而不会浪费空间,因为只存储了序数位置。
【讨论】:
【参考方案7】:对于使用 CASE ORDER BY 的新手来说,这可能很有用
ORDER BY
CASE WHEN GRADE = 'A' THEN 0
WHEN GRADE = 'B' THEN 1
ELSE 2 END
【讨论】:
【参考方案8】:@bobflux 的answer 很棒。我想通过添加一个使用建议方法的完整查询来扩展它。
select tt.id, tt.x_field
from target_table as tt
-- Here we join our target_table with order_table to specify custom ordering.
left join
(values ('f', 1), ('p', 2), ('i', 3), ('a', 4)) as order_table (x_field, order_num)
on order_table.x_field = tt.x_field
order by
order_table.order_num, -- Here we order values by our custom order.
tt.x_field; -- Other values can be ordered alphabetically, for example.
这里是完整的demo。
【讨论】:
【参考方案9】:您可以按选定的列或其他表达式排序。
这里是一个例子,如何按 case-statement 的结果排序:
SELECT col1
, col2
FROM tbl_Bill
WHERE col1 = 0
ORDER BY -- order by case-statement
CASE WHEN tbl_Bill.IsGen = 0 THEN 0
WHEN tbl_Bill.IsGen = 1 THEN 1
ELSE 2 END
结果将是一个以“IsGen = 0”行开头的列表,然后是“IsGen = 1”行,最后是所有其他行。
您可以在最后添加更多订单参数:
SELECT col1
, col2
FROM tbl_Bill
WHERE col1 = 0
ORDER BY -- order by case-statement
CASE WHEN tbl_Bill.IsGen = 0 THEN 0
WHEN tbl_Bill.IsGen = 1 THEN 1
ELSE 2 END,
col1,
col2
【讨论】:
虽然这段代码 sn-p 可以解决问题,但它没有解释为什么或如何回答这个问题。请include an explanation for your code,因为这确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。【参考方案10】:由于我没有足够的声誉来写评论,所以将此添加为新答案。
您可以在 order by 子句中添加 asc 或 desc。
ORDER BY x_field='A' ASC, x_field='I' DESC, x_field='P' DESC, x_field='F' ASC
这使得I在前,P在后,A作为最后一个,F在最后一个之前。
【讨论】:
【参考方案11】:如果您之后使用 mysql 4.0,请考虑使用 FIELD()
。它通过下一个参数返回第一个参数的索引位置,并且区分大小写。
ORDER BY FIELD(x_field, 'f', 'p', 'i', 'a')
【讨论】:
【参考方案12】:您可以使用位置(文本中的文本)来排序序列
【讨论】:
以上是关于sql ORDER BY 按特定顺序排列多个值?的主要内容,如果未能解决你的问题,请参考以下文章
具有特定顺序的 SQL ORDER BY,首先以特定单词开头,然后是升序 [重复]
若SQL语句中的ORDER BY短语中指定了多个字段,则( )。