2012-01-03 77 views
1

我的数据库中有新闻文章和博客文章。两者的主键都是在两个表中唯一的ItemID。在多个表中按日期分组的Mysql计数记录

文章是在具有以下字段

  • ITEM_ID
  • 标题
  • date_posted

的相关博客文章表具有以下的表字段

  • ITEM_ID
  • 标题
  • date_posted

两个表具有独特他们额外的字段。

我有第三个表,包含关于文章和帖子的元信息。

项目表具有以下字段

  • ITEM_ID
  • SOURCE_ID
  • ...

每一个博客帖子和文章在项目表和记录的记录在各自的表格中。

我想要做的是构建一个查询,将计算每天张贴的项目数量。我可以使用按日期分组计数的一张表执行此操作,但如何在一个查询中将合并文章和帖子计数为

回答

2

类似民主党,但稍微简单:

select date_posted, count(*) 
from (select date_posted from article union all 
     select date_posted from blogposts) v 
group by date_posted 
+0

+1:我无法在MySQL上测试,但在SQL Server上测试时,它的优化效果非常好(我没有预计) – MatBailie 2012-01-03 16:42:57

+1

***注意:***同样假设索引与'date_posted'作为第一个领域的最佳性能。 – MatBailie 2012-01-03 16:43:37

0
select item_id, date_posted from blogposts where /* some conditions */ 
union all select item_id, date_posted from articles where /* some conditions */ 

你可能需要将它放入一个子查询,如果你愿意的话,在运行时group by与其他表,加入它。但重要的是union是您用来组合来自不同表格的数据的运算符。 union all告诉数据库你不需要它来组合重复记录,因为你知道这两个表永远不会共享一个item_id,所以它有点快(可能)。

+0

我试图做一个工会,但什么其实我试图做的,这不是在OP明确的是计数的结果结合起来。所以这两个选择是'select count(item_id)from blogposts group by date'和'select count(item_id_ from articles group by date') – applechief 2012-01-03 16:16:42

1

我会用这个不同的表设计,类型和子类型。 Your Items表具有单列主键,而您的Blog_Posts和Articles表的主键与Items表的外键具有相同的ID。这将使得这样做非常容易,并且有助于确保数据的完整性。

与您现有的设计,你最好的选择可能是这样的:

SELECT 
    I.item_id, 
    I.source_id, 
    COALESCE(A.date_posted, B.date_posted) AS date_posted, 
    COUNT(*) AS date_count 
FROM 
    Items I 
LEFT OUTER JOIN Articles A ON 
    A.item_id = I.item_id AND 
    I.source_id = 'A' -- Or whatever the Articles ID is 
LEFT OUTER JOIN Blog_Posts B ON 
    B.item_id = I.item_id AND 
    I.source_id = 'B' -- Or whatever the Blog_Posts ID is 
GROUP BY 
    I.item_id, 
    I.source_id, 
    COALESCE(A.date_posted, B.date_posted) 

您也可以尝试使用UNION

SELECT 
    SQ.item_id, 
    SQ.source_id, 
    SQ.date_posted, 
    COUNT(*) AS date_count 
FROM 
    (
     SELECT I1.item_id, I1.source_id, A.date_posted 
     FROM Items I1 
     INNER JOIN Articles A ON A.item_id = I1.item_id 
     WHERE I1.source_id = 'A' 
     UNION ALL 
     SELECT I2.item_id, I2.source_id, B.date_posted 
     FROM Items I2 
     INNER JOIN Articles B ON B.item_id = I2.item_id 
     WHERE I2.source_id = 'B' 
    ) 
3

你能做到的两种方式。
1.加入所有内容,然后汇总(请参阅Tom H的回答)。
2.聚合每个表,将它们联合起来,然后重新聚合。

选项1可能看起来更短,但意味着您可能无法从根表上的INDEX获益(因为它们必须为JOIN重新排序)。所以我会展示选项2,这是您以任何方式走向的方向。

SELECT 
    date_posted, 
    SUM(daily_count) AS daily_count 
FROM 
    (
    SELECT date_posted, COUNT(*) AS daily_count FROM article GROUP BY date_posted 
    UNION ALL 
    SELECT date_posted, COUNT(*) AS daily_count FROM blogposts GROUP BY date_posted 
) 
    AS combined 
GROUP BY 
    date_posted 

这应该是最快的,前提是你必须在每个表中的索引,其中date_posted是该指数第一场。否则,表格仍然需要重新排序才能进行汇总。

+0

只需记住第二个解决方案,即某些聚合有点复杂。例如(平均值),但这是一个很好的解决方案 – 2012-01-03 19:25:43

+0

是一个“小”的技巧,是的,但是因为你可以返回SUM(value)和COUNT(*),所以你可以做平均值,你甚至可以做STDev如果数据格式合适,Mark Ba​​nnister的答案更简单: – MatBailie 2012-01-03 19:40:58