从此表的多个列中选择一次“唯一值”,以保留原始顺序?

时间:2018-10-20 02:35:48

标签: sql postgresql

我有一个(子查询)表,该表列出了我朋友的用餐偏好。每餐只能吃一次,每个人只能吃一餐。

row_number person_id   meal_id
   1           1           3       
   2           2           1
   3           2           2
   4           2           3      
   5           3           1   
   6           3           2
   7           3           3

选择顺序由表格的原始顺序决定,所以我希望结果为:

person_id   meal_id
   1           3       
   2           1   
   3           2

因为用户1吃了饭1,用户3吃了饭2。我认为可以通过根据原始顺序在两列中选择不同的值来解决此问题,但是我无法弄清楚如何编写该查询。任何帮助表示赞赏。

更新为原始表添加了row_number

1 个答案:

答案 0 :(得分:2)

如果我正确理解,这是一个相当复杂的图形遍历问题。我首先应该指出,没有很多解决方案,就无法保证最佳解决方案。但是您可以使用递归CTE实现贪婪算法:

with recursive t as (
      select v.*
      from (values (1, 1, 3), (2, 2, 1), (3, 2, 2), (4, 2, 3), (5, 3, 1), (6, 3, 2), (7, 3, 3)
           ) v(row_number, person_id, meal_id)
     ),
     cte (row_number, person_id, meal_id, rows, persons, meals, lev) as (
     select row_number, person_id, meal_id, array[row_number], array[person_id], array[meal_id], 1 as lev
     from t
     where row_number = 1
     union all
     select t.row_number, t.person_id, t.meal_id,
            (case when t.person_id = any(cte.persons) or t.meal_id = any(cte.meals)
                  then cte.rows
                  else array_append(cte.rows, t.row_number)
             end),
            (case when t.person_id = any(cte.persons) or t.meal_id = any(cte.meals)
                  then cte.persons
                  else array_append(cte.persons, t.person_id)
             end),
            (case when t.person_id = any(cte.persons) or t.meal_id = any(cte.meals)
                  then cte.meals
                  else array_append(cte.meals, t.meal_id)
             end),
            cte.lev + 1
     from cte join
          t
          on t.row_number = cte.row_number + 1
    )
select t.*
from t cross join
     (select rows from cte order by lev desc fetch first 1 row only) as last1
where t.row_number = any (last1.rows);

Here是db <>小提琴。