复杂组由mysql查询

时间:2010-08-05 08:24:27

标签: sql mysql database facebook news-feed

我有一个包含以下行的表:

id. user_id, type  - link 

 1. 555, image - http://1
 2. 555, image - http://2
 3. 654, image  - http://3
 4. 245, video - http://..
 5. 555, image - http://..
 6. 878, text  - http://..

我想按日期对类型(图像)进行分组,因此它们显示为单行。在这个例子中,前两个图像将合并在一起,输出将如下所示,同时请注意,如果它不是同一个用户,那么它将不会为该用户分组。

输出

1. 555, image - http://1, http://2  ** GROUPED BY DATE, if they are same type and not break type after it.
2. 654, image - http://3
3. 245, video - http://..
4. 555, image - http://..
5. 878, text  - http://.

顺便说一下像新闻提要做facebook,如果有人有更好的想法,请分享。

5 个答案:

答案 0 :(得分:3)

SELECT `date`, `user_id`, `type`, GROUP_CONCAT(`link`)
FROM `table`
GROUP BY `date`, `user_id`, `type`

答案 1 :(得分:1)

你有什么理由需要在SQL中执行此操作吗?我尝试在SQL中进行数据收集,并将格式化推送到调用SQL的代码中。

我会做一个简单的SQL查询,检索所有图像文件,但按user_id / date排序。然后我的代码将遍历结果,将每个图像文件连接到相同的输出行,直到用户id / date更改为止,在这种情况下,我们知道我们需要使用新的用户id / date开始一个新行。

这也可以更容易地在文本周围进行任何时髦的格式化,特别是如果您打算发出HTML。

答案 2 :(得分:1)

这在SQL中并不容易,因为它依赖于顺序,哪种SQL不适合。

查询非常笨拙,所以我先完全放弃,然后细分显示它是如何放在一起的。

SELECT @rownum:=@rownum+1 AS id, t.user_id, type, date, urls FROM
 (SELECT MIN(ID) AS original_id, user_id, type, date, GROUP_CONCAT(url) urls FROM
  (SELECT i1.*, 
   IF(i1.type='image', 
     IFNULL((SELECT MIN(i2.ID)-1 FROM Items i2
             WHERE i2.ID>i1.ID AND 
                  (i2.type!=i1.type OR i1.user_id!=i2.user_id OR i1.date!=i2.date)), 
            (SELECT MAX(id) FROM Items)), 
     i1.ID) AS lastRow,
   IF (i1.type='image', 
     IFNULL(SELECT MAX(i3.ID)+1 FROM Items i3 
             WHERE i3.ID<=i1.ID AND 
                  (i3.type!=i1.type OR i1.user_id!=i3.user_id OR i1.date!=i3.date)), 
            (SELECT MIN(id) FROM Items)), 
      i1.ID) AS firstRow) AS groupItems
  GROUP BY user_id, type, date, firstRow, lastRow) t, (SELECT @rownum:=0) r
  ORDER BY t.original_id; 

查询使用相关子查询来查找每个图像组的开始和结束ID。组边界是不同类型,用户或日期的项目。

SELECT i1.ID, 
  IF(i1.type='image', 
     IFNULL((SELECT MIN(i2.ID)-1 FROM Items i2
             WHERE i2.ID>i1.ID AND 
                  (i2.type!=i1.type OR i1.user_id!=i2.user_id OR i1.date!=i2.date)), 
            (SELECT MAX(id) FROM Items)), 
     i1.ID) AS lastRow,
  IF (i1.type='image', 
     IFNULL(SELECT MAX(i3.ID)+1 FROM Items i3 
             WHERE i3.ID<=i1.ID AND 
                  (i3.type!=i1.type OR i1.user_id!=i3.user_id OR i1.date!=i3.date)), 
            (SELECT MIN(id) FROM Items)), 
      i1.ID) AS firstRow

对于每个项目,firstRow / lastRow列给出组的开始和结束。然后我们可以使用GROUP_CONCAT来连接所有URL。为了保留顺序,输出MIN(id),给出每个组的第一个ID。

SELECT MIN(id) AS original_id, user_id, type, date, GROUP_CONCAT(url) urls FROM
 (SELECT i1.*, 
  IF(i1.type='image', 
     IFNULL((SELECT MIN(i2.ID)-1 FROM Items i2
             WHERE i2.ID>i1.ID AND 
                  (i2.type!=i1.type OR i1.user_id!=i2.user_id OR i1.date!=i2.date)), 
            (SELECT MAX(id) FROM Items)), 
     i1.ID) AS lastRow,
  IF (i1.type='image', 
     IFNULL(SELECT MAX(i3.ID)+1 FROM Items i3 
             WHERE i3.ID<=i1.ID AND 
                  (i3.type!=i1.type OR i1.user_id!=i3.user_id OR i1.date!=i3.date)), 
            (SELECT MIN(id) FROM Items)), 
      i1.ID) AS firstRow) AS groupItems
 GROUP BY user_id, type, date, firstRow, lastRow

最后,要获取新表的连续ID,请使用变量来计算排名:

SELECT @rownum:=@rownum+1 AS id, user_id, type, date, urls FROM
 (SELECT MIN(ID) AS original_id, user_id, type, date, GROUP_CONCAT(url) urls FROM
  (SELECT i1.*, 
   IF(i1.type='image', 
     IFNULL((SELECT MIN(i2.ID)-1 FROM Items i2
             WHERE i2.ID>i1.ID AND 
                  (i2.type!=i1.type OR i1.user_id!=i2.user_id OR i1.date!=i2.date)), 
            (SELECT MAX(id) FROM Items)), 
     i1.ID) AS lastRow,
   IF (i1.type='image', 
     IFNULL(SELECT MAX(i3.ID)+1 FROM Items i3 
             WHERE i3.ID<=i1.ID AND 
                  (i3.type!=i1.type OR i1.user_id!=i3.user_id OR i1.date!=i3.date)), 
            (SELECT MIN(id) FROM Items)), 
      i1.ID) AS firstRow) AS groupItems
  GROUP BY user_id, type, date, firstRow, lastRow) t, (SELECT @rownum:=0) r
  ORDER BY t.original_id; 

SQL最适合处理无序数据集,而不是序列,就像这里一样。 如果您可以在演示文稿代码中执行此操作,或者可能在应用程序层中执行此操作,我认为这将更快,更灵活。手动编码的解决方案可以在一次通过数据时找到每个组的开始和结束。我怀疑SQL查询是否会像那样有效地执行。

答案 3 :(得分:0)

这个查询可以解决问题:

select id, user_id, `type`, group_concat(link) from images
group by user_id, `type`, date
order by id

答案 4 :(得分:0)

我可能会考虑使用不同的数据存储区,例如CouchDB或RavenDB。这在提供此类内容方面要好得多,而且不必处理外键或连接。

只需对所有朋友的数据库进行连续复制即可。

最终,您必须预先查询或放弃关系模型才能恢复速度。