我正在使用POSTGRESQL,但我找不到如何解决问题。我有一个名为Foobar的模型。它的一些属性是:
FOOBAR
check_in:datetime
qr_code:string
city_id:integer
在这个表中有很多冗余(qr_code不是唯一的),但这不是我现在的问题。我想要得到的是具有相同qr_code并且已经在一个众所周知的城市群中的foobar,它们已经在不同时刻检查过。 我通过查询得到了这个:
SELECT * FROM foobar AS a
WHERE a.city_id = 1
AND EXISTS (
SELECT * FROM foobar AS b
WHERE a.check_in < b.check_in
AND a.qr_code = b.qr_code
AND b.city_id = 2
AND EXISTS (
SELECT * FROM foobar as c
WHERE b.check_in < c.check_in
AND c.qr_code = b.qr_code
AND c.city_id = 3
AND EXISTS(...)
)
)
其中'...'代表更多查询,以获得更多具有相同qr_code,不同check_in日期和众所周知城市的人。
我的问题是我想通过qr_code对此进行分组,并且我想要显示每个qr_code的check_in字段,如下所示:
2015-11-11 14:14:14 =&gt; [2015-11-11 14:14:14,2015-11-11 16:16:16,2015-11-11 17:18:20](这个为每个不同的qr_code)
其中左侧的数据是该qr_code的“较小”日期,右侧部分是该qr_code的所有其他日期,包括第一个。 这可能只与sql查询有关吗?我问这个是因为我实际上是用rails做这个应用程序,我知道我可以用ruby的数组方法做一个不同的方法(这个解决方案也很受欢迎)
答案 0 :(得分:0)
如果我正确地解释了你的问题,你可以用recursive CTE来解决这个问题:
假设您有一个给定的城市列表,必须按相同的qr_code
按顺序访问。您的文字没有这么说,但您的查询表明了这一点。
WITH RECURSIVE
c AS (SELECT '{1,2,3}'::int[] AS cities) -- your list of city_id's here
, route AS (
SELECT f.check_in, f.qr_code, 2 AS idx
FROM foobar f
JOIN c ON f.city_id = c.cities[1]
UNION ALL
SELECT f.check_in, f.qr_code, r.idx + 1
FROM route r
JOIN foobar f USING (qr_code)
JOIN c ON f.city_id = c.cities[r.idx]
WHERE r.check_in < f.check_in
)
SELECT qr_code, array_agg(check_in) AS check_in_list
FROM (
SELECT *
FROM route
ORDER BY qr_code, idx -- or check_in
) sub
HAVING count(*) = (SELECT array_length(cities) FROM c);
GROUP BY 1;
在第一个(非递归)CTE c
中将列表作为数组提供。
在递归部分中,从第一个城市中的任何行开始,沿着数组行进,直到最后一个元素。
在最终SELECT
按顺序汇总您的check_in
列。只返回已访问阵列的所有城市的qr_code
。
类似: