我有一个(子查询)表,该表列出了我朋友的用餐偏好。每餐只能吃一次,每个人只能吃一餐。
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
。
答案 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 <>小提琴。