【问题标题】:Distinct on column using custom order使用自定义顺序区分列
【发布时间】:2018-11-01 11:52:32
【问题描述】:

我有一个数据库视图。

此时它返回在id 列中可以有重复条目的行。 我想做以下事情:

SELECT DISTINCT ON (id) USING DESCRIBED BELOW RULE -- of course it is not valid sql
  id
  type

type 列可以有 3 个值:

  • x
  • y
  • z

如果存在id相同但type不同的行,DISTINCT的规则如下:

  • 首先选择类型为x 的行
  • 如果没有x,则选择类型为y 的行
  • 如果没有x 且没有y,则选择类型为z 的行

所以如果我有 3 行:

id    type
1     'y'
1     'x'
2     'z'

预期的结果将是

id    type
1     'x'
2     'z'

有没有办法做到这一点?

【问题讨论】:

    标签: database postgresql distinct database-view


    【解决方案1】:

    您可以将层次结构放入ORDER BY 中的CASE 表达式中

    SELECT DISTINCT ON (id) * 
    FROM   ( VALUES (1, 'y'), 
                    (1, 'x'), 
                    (2, 'z') ) s(id, type) 
    ORDER  BY id, 
              CASE type 
                WHEN 'x' THEN 1 
                WHEN 'y' THEN 2 
                WHEN 'z' THEN 3 
              END; 
    

    Demo

    【讨论】:

    • 我不明白它是如何工作的,ORDER BYDISTINCT 之前被“触发”了吗?所以它首先得到重复的行,按type 排序,然后DISTINCT 只选择第一个?
    • 你能回答我的问题吗?
    • @Andrey Deineko:这应该回答你的问题:stackoverflow.com/a/46142892
    【解决方案2】:

    如果您的值实际上是按字母顺序排列的(如您的示例中所示),那将非常简单 - 您只需对值进行排序:

    SELECT DISTINCT ON (id)
        id,
        type
    FROM mytable m
    ORDER BY id, type
    

    demo:db<>fiddle

    如果没有,您将需要一个表格来存储排名值及其排名顺序。或者你像我一样用子查询来模拟它:

    SELECT DISTINCT ON (id)
        id,
        type
    FROM mytable m
    JOIN (VALUES (1, 'x'), (2, 'y'), (3, 'z')) AS r (rank_id,value)
    ON r.value = m.type
    ORDER BY id, r.rank_id
    

    如果您的类型数据确实是固定的,您可以考虑使用enum type,它默认是有序类型。查询看起来像上面的第一个:

    demo: db<>fiddle

    但请注意,更改枚举(添加、删除、重新排列值)可能非常困难。因此,仅在类型确实固定时才建议使用。否则,使用带有外键的单独表带您回到第二部分。

    【讨论】:

    • 我喜欢排名表的想法,但不知何故它不起作用。艰难的@Kaushik Nayak 建议的CASE 选项奏效了。至于枚举:是的,我尽量避免使用枚举
    • 为什么不起作用?这是一个小提琴样本:dbfiddle.uk/…
    猜你喜欢
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    • 2021-04-02
    • 1970-01-01
    • 2023-03-18
    • 2021-09-18
    相关资源
    最近更新 更多