如何按多行值分组?

时间:2015-07-24 03:53:20

标签: sql ruby-on-rails ruby postgresql recursive-query

我正在使用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的数组方法做一个不同的方法(这个解决方案也很受欢迎)

1 个答案:

答案 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

类似:

相关问题