多个表订购GROUP BY或不同的SQL

时间:2013-04-18 15:53:06

标签: sql postgresql join group-by distinct

我一直试图解决这个问题,但没有运气,所以如果有人可以帮助我,那就太好了。

我有两张桌子。物品和物品标志。

物品

id        name       levelid        containertypeid        roomid        userid      timestamp
--        ----       -------        ---------------        ------        ------      -----
1         Item 1     0              0                      3             5           1365072108
2         Item 2     0              0                      3             5           1365342108
3         Item 3     0              0                      3             5           1389072108
4         Item 4     0              0                      3             5           1365085108
5         Item 5     2              3                      3             5           1365962108
6         Item 6     1              3                      3             5           1365322108

Item_Flags

id        itemid     flagid        userid        timestamp
--        ----       -------       -------       ---------
1         1          1              5            1365072108
2         1          5              5            1365342108
3         1          2              5            1389072108
4         1          3              5            1365085108
5         2          4              5            1365762108
6         2          1              5            1365921087
7         2          3              5            1365252108
8         3          6              5            1365982108
9         3          7              5            1365312108
10        3          8              5            1365342108

目标

我要做的是获取所有项目的列表,按降序时间戳排序。所以,实际上,我想要一个基于最新时间戳的项目列表,从我们更新实际项目或添加项目标志时开始。每次针对特定项目添加标记时或者每当更新项目名称或级别时,应用程序都会更新时间戳。问题是,如果我想取回名称,levelid等字段,我就无法运行GROUP BY,因为我在聚合函数中使用它们,因此实际值不会回来。如果我不对它们进行分组,我显然会根据它有多少个标记获得每个项目的多个结果。这是我的疑问:

SELECT 
                items.id,
                items.name,   
                items.levelid,
                items.containertypeid,
                items.roomid,
                items.userid
        FROM 
                items
        LEFT OUTER JOIN item_flags ON
                items.id = flags.itemid
        WHERE
                items.levelid = 0 AND 
                items.containertypeid = 0 AND 
                items.room = 3 AND
                items.userid = 5
        GROUP BY 
               items.id
        ORDER BY 
               items.timemodified DESC
               item_flags.timemodified DESC

如果我将除了items.id之外的所有选择字段包装在聚合函数中并完全删除ORDER,我可以使用此工作,但是当我将它们取回并且需要它们时,我需要使用这些字段!我现在还不确定查询中的逻辑是否有意义,因为虽然我说flags.itemid等于items.id,但那里有一对多的关系。

我看过SQL Query - Grouping with multiple tables,但是那里没有ORDER BY,我无法弄清楚如何让它工作!

使用PG SQL。

谢谢!

==================================

事实证明,在这一切的最后,查询也必须与MySQL一起使用而且With显然不起作用。所以我们提出了一个不同的解决方案,我正在运行测试,我会尽快发布,以防它可能对其他人有用。

3 个答案:

答案 0 :(得分:1)

您可以使用以下GROUP BY

GROUP BY
            items.id,
            items.name,   
            items.levelid,
            items.containertypeid,
            items.roomid,
            items.userid

由于items.id是唯一的,因此会将记录分组为“GROUP BY items.id”。

对于数据库来说,这似乎更有用,但是由数据库决定它只能检查分组的ID。

答案 1 :(得分:1)

一种方法:

with cte as
(SELECT id,
        timestamp,
        name,   
        levelid,
        containertypeid,
        roomid,
        userid
 FROM items
 UNION ALL
 SELECT itemid id,
        timestamp,
        NULL as name,
        NULL as levelid,
        NULL as containertypeid,
        NULL as roomid,
        NULL as userid
 from item_flags)
select id,
       max(timestamp) as timestamp,
       max(name) as name,   
       max(levelid) as levelid,
       max(containertypeid) as containertypeid,
       max(roomid) as roomid,
       max(userid) as userid
from cte
group by id
order by 2 desc

SQLFiddle here

可替换地:

select id,
       max(timestamp) as timestamp,
       max(name) as name,   
       max(levelid) as levelid,
       max(containertypeid) as containertypeid,
       max(roomid) as roomid,
       max(userid) as userid
from 
(SELECT id,
        timestamp,
        name,   
        levelid,
        containertypeid,
        roomid,
        userid
 FROM items
 UNION ALL
 SELECT itemid id,
        timestamp,
        NULL as name,
        NULL as levelid,
        NULL as containertypeid,
        NULL as roomid,
        NULL as userid
 from item_flags) sq
group by id
order by 2 desc

SQLFiddle here

答案 2 :(得分:-1)

所以最后,我们已经解决了这个问题:

SELECT 
items.id, 
max(items.name) as name,
max(item_flags.flagid) as flagid,
max(COALESCE(item_flags.timestamp, items.timestamp)) AS tm
FROM   
items
LEFT JOIN 
item_flags 
ON 
item_flags.itemid = items.id 
GROUP BY items.id 
ORDER BY tm DESC