【问题标题】:Combining SUM(), GROUP_BY() and LEFT_JOIN() returns incorrect results: how to fix?组合 SUM()、GROUP_BY() 和 LEFT_JOIN() 会返回不正确的结果:如何解决?
【发布时间】:2011-03-18 14:39:30
【问题描述】:

我正在编写一个查询,该查询应返回每天/每月/每年多个用户的汇总小时数。

表格如下所示:

+------------------------------------------+
| id | entity_id | minutes | person | date |
+------------------------------------------+

输出应该的样子:

+----------------------------+
| year | month | day | hours |
| 2008 | 12    | 1   | 30    |
| 2008 | 12    | 2   | 40    |
| 2008 | 12    | 3   | 23    |
+----------------------------+

相反,hours 通常更多是由于left join 引起的返回行。

问题是我需要根据链接到相应实体的标签来查询这个表。当我加入这两个表(提供链接的tag_entity 和提供实际标签名称的tags)时,我的SUM() 不再有效,因为返回的结果太多。

查询:

select 
    date_format(from_unixtime(date), '%Y-%m-%d') as myDate,
    ROUND(SUM(time) / 60,1) as hours

from time h

left join tag_entity te on te.entity_id = h.entity_id
left join tags t on t.tag_id = te.tag_id

where (t.tag_name NOT IN ('foo', 'bar', 'baz') OR t.tag_name IS NULL) 

group by
    myDate

order by
    hours DESC, myDate ASC

我该如何解决这个问题?

编辑:

这是tagtag_entity 的架构:

Tag:

+----------+-------------+
| Field    | Type        |
+----------+-------------+
| tag_id   | int(11)     |
| tag_name | varchar(50) |
+----------+-------------+

还有tag_entity

+-----------+---------+
| Field     | Type    |
+-----------+---------+
| id        | int(11) |
| tag_id    | int(11) |
| entity_id | int(11) |
+-----------+---------+

【问题讨论】:

  • 也许我还没有喝足够的咖啡,但我在推断您的架构时遇到了麻烦。您能否发布标签和 tag_entity 架构的相关部分?另外,在哪个表中定义了“日期”和“时间”?
  • @Andrew 感谢您的回复。我添加了模式。 datetime 在我的 time 表中。
  • 您选择 from t 并执行 left join tags t - 语法错误。你忘了输入主表名吗?
  • @Marc 哎呀。贴出查询稍作调整,原版不会出现此问题。将在此示例中修复。
  • 您想要没有标签之一的实体('foo'、'bar'、'baz'),还是想要包含除 ('foo'、'bar' 之外的标签的实体,“巴兹”)?如果实体 1 有标签 'foo' 和标签 'me',是否应该包括在内?

标签: mysql group-by left-join


【解决方案1】:

GROUP BY结果进行分组,而不是单独对表格行进行分组。

根据您的评论只返回时间表中未链接到这些标签之一的行

SELECT 
    date_format(from_unixtime(date), '%Y-%m-%d') as myDate,
    ROUND(SUM(time) / 60,1) as hours
FROM `time` h
  LEFT JOIN (
    SELECT DISTINCT te.entity_id
    FROM tag_entity te
      LEFT JOIN tags t on t.tag_id = te.tag_id
    WHERE te.entity_id IS NOT NULL AND t.tag_name IN ('foo', 'bar', 'baz')
  ) g ON h.entity_id = g.entity_id
WHERE g.entity_id IS NULL
group by
    myDate

order by
    hours DESC, myDate ASC

【讨论】:

  • 哇,你真的做到了。非常感谢,你刚刚度过了我的周末。
【解决方案2】:
select 
    date_format(from_unixtime(date), '%Y-%m-%d') as jaar,
    ROUND(SUM(time) / 60,1) as uren

from time h

left join tag_entity te on te.entity_id = h.entity_id
left join tags t on t.tag_id = te.tag_id

where (t.tag_name NOT IN ('foo', 'bar', 'baz') OR t.tag_name IS NULL) 

group by jaar

order by
    uren DESC, jaar ASC

【讨论】:

  • 除了将日期格式更改为一列之外,这没有解决任何问题。不过,为了简化查询,我将其更改为只返回一个日期列。
  • 你测试了吗?这不仅仅是日期格式的变化。您查询的问题是您按所有年份的月份以及所有月份和年份的日期进行分组,例如所有年份的所有 1 月的总和。它与左连接无关。除此之外你不是说AND t.tag_name IS NOT NULL吗?
  • 是的,我测试了它,但没有结果,很遗憾。 GROUP BY 子句不应该按照您描述的方式工作:它结合了组参数。您的示例产生完全相同的输出。
【解决方案3】:

可能你想要这样的东西:

select 
    date_format(from_unixtime(date), '%Y-%m-%d') as myDate,
    ROUND(SUM(time) / 60,1) as hours

from time h

left join tag_entity te on te.entity_id = h.entity_id

where NOT EXISTS(select te.entity_id

                 from tag_entity te

                 join tags t on t.tag_id = te.tag_id

                 where te.tag_entity = h.entity_id  AND t.tag_name IN ('foo', 'bar', 'baz')) 

group by
    myDate

order by
    hours DESC, myDate ASC

【讨论】:

    猜你喜欢
    • 2016-10-26
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 2012-07-04
    相关资源
    最近更新 更多