sql ORDER BY特定值的多个值?


94

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

例:

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,因为我需要返回特定的记录值
  • 在x_field IN('f','p','i','a')中,我需要所有值,因为我试图使用一个查询进行多个验证测试。并且x_field值不是DESC / ASC顺序

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


也许工会呢?按照要返回结果的顺序构造单独的查询,然后对那些查询进行并集?
kinakuta 2011年

Answers:


181
...
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

29

您可以将LEFT JOIN与“ VALUES('f',1),('p',2),('a',3),('i',4)”一起使用,并在订单中使用第二列-通过表达式。如果您有很多值,Postgres将使用哈希联接,该哈希联接比大型CASE快得多。而且更容易自动生成。

如果此订购信息是固定的,则它应该具有自己的表。


6
这是迄今为止最优雅的解决方案!
jnns 2012年

28

尝试:

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

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


Postgres是否支持隐式布尔值?如果是这样,布尔值如何排序?
gbn

我喜欢这个解决方案,但是它什么也没有返回。
Phill Pafford

@gbn,是,false <true。我本来希望这能奏效。
Andrew Lazarus

7
是的,它在Postgres中有效。此解决方案的注意事项是您得到的结果以相反的顺序排序。因此,您必须按相反顺序放置字段:ORDER BY x_field ='A',x_field ='I',x_field ='P',x_field ='F',
igo

16

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

10

我找到了一个更清洁的解决方案:

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

注意:array_position需要Postgres v9.5或更高版本。


1
重要的是要注意array_position()仅在Postgres v9.5及更高版本afaik中可用。
bigsee

谢谢,这比CASE方法更可取。也适用于整数;array_position(ARRAY[1, 0]::integer[], x_field)
保罗·沃森

7

CASEORDER BY建议都应该工作,但是我要提出一个不同颜色的马。假定仅存在合理数量的值,x_field并且您已经知道它们的含义,请使用F,P,A和I作为值创建枚举类型(加上其他可能的值)。枚举将按照其CREATE语句隐含的顺序进行排序。另外,您可以使用有意义的值名称(您的实际应用程序可能会使用,而您刚刚对它们进行了屏蔽以确保机密性),而不会浪费空间,因为仅存储了序数位置。


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

结果将是一个列表,列表以“ 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

尽管此代码段可以解决问题,但并未说明原因或答案。请附上代码说明,因为这确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。
塞缪尔·菲利普

0

对于使用CASE进行ORDER BY的新手来说,这可能会有用

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.