多个值按特定顺序排列?

好,我有一个表与索引键和一个非索引字段。 我需要查找具有某个值的所有记录并返回该行。 我想知道我是否可以按多个值排序。

例如:

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 视为测试结果,我需要验证条件下的所有记录。我想通过失败的值和传递的值来排序测试结果。因此,我可以先验证失败的值,然后使用 ORDERBY 验证传递的值。

我不能做的:

  • GROUPBY,因为我需要返回特定的记录值
  • WHERE x _ field IN (‘ f’,‘ p’,‘ i’,‘ a’) ,我需要所有的值,因为我试图使用一个查询进行多个验证测试。并且 x _ field 值不是 DESC/ASC 顺序

写完这个问题后,我开始觉得我需要重新考虑一下,哈哈!

173701 次浏览
...
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

试试:

ORDER BY x_field='f', x_field='p', x_field='i', x_field='a'

您是在正确的轨道上,但是通过将 X _ field仅放在 F值上,其他三个被视为常量,并且不与数据集中的任何内容进行比较。

使用 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

CASEORDER BY的建议都应该工作,但我要建议一匹不同颜色的马。假设对于 x_field只有合理数量的值,并且您已经知道它们是什么,那么创建一个以 F、 P、 A 和 I 作为值的 枚举类型(加上任何其他可能的值)。枚举将按照它们的 CREATE语句所暗示的顺序排序。此外,您可以使用有意义的值名称 & mash; 您的实际应用程序可能会这样做,并且您刚刚为了保密而屏蔽了它们,而没有浪费空间,因为只存储序号位置。

您可以使用带有“ VALUES (‘ f’,1) ,(‘ p’,2) ,(‘ a’,3) ,(‘ i’,4)”的左连接,并在 order-by 表达式中使用第二列。Postgres 将使用一个哈希连接,如果你有很多值,它将比大型 CASE 快得多。而且更容易自动生成。

如果这个排序信息是固定的,那么它应该有自己的表。

您可以使用位置(文本中的文本)为顺序的序列

我找到了一个更干净的解决方案:

ORDER BY array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field)

注意: array _ position 需要 Postgres v9.5或更高版本。

可以按选定的列或其他表达式进行排序。

这里有一个例子,如何按照 case 语句的结果排序:

  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”行开始的 List,其次是“ 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

对于刚接触 订购人凯斯的人来说,这可能是有用的

ORDER BY
CASE WHEN GRADE = 'A' THEN 0
WHEN GRADE = 'B' THEN 1
ELSE 2 END

因为我没有足够的声誉来写评论,所以添加这个作为一个新的答案。

您可以将 asc 或 desc 添加到以子句为顺序的顺序中。

ORDER BY x_field='A' ASC, x_field='I' DESC, x_field='P' DESC, x_field='F' ASC

也就是说我是第一个,P 是第二个,A 是最后一个,F 是最后一个。

@ bobflux 的 回答非常棒,我想通过添加一个完整的查询来扩展它,这个查询使用了提议的方法。

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.

这是完整的 小样

如果以后要使用 MySQL 4.0,可以考虑使用 FIELD()。它通过下一个参数返回第一个参数的索引位置,并且区分大小写。

ORDER BY FIELD(x_field, 'f', 'p', 'i', 'a')