【问题标题】:How can I use aliases on GROUP BY clause?如何在 GROUP BY 子句中使用别名?
【发布时间】:2016-09-06 22:32:36
【问题描述】:

这是我的查询:

SELECT  SUM(score) score,
    type,
    context,
    post_id,
    e.table_code,
    comment_id,
    MIN(seen) seen,
    MAX(date_time) d_t,
    (CASE   WHEN FROM_UNIXTIME(MAX(date_time)) >= CURDATE() THEN 'today'
        WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
        WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
        ELSE 'in last month'
    END) as range_day
FROM `events` e
WHERE e.id IN ($ids)
GROUP BY type, post_id, e.table_code, comment_id, range_day
ORDER BY seen, MAX(date_time) desc, MAX(e.id) desc

它会抛出这个错误:

#1056 - 无法在“range_day”分组

如果我从GROUP BY 子句中删除range_day,那么它也可以工作。但我还需要根据range_day 对结果进行分组。我该怎么做?

【问题讨论】:

  • range_day 是计算列的别名。所以,它不能用于group by。请改用实际计算。
  • 在分组时重复你的案例将起作用
  • range_day 是使用聚合函数 MAX 计算得出的。但是不能在 group by 子句中使用聚合函数。
  • @vkp 你是什么意思“实际计算”?是date_time 专栏吗?嗯,这是一个唯一的值(几乎) .. 所以聚合函数不会按预期工作。
  • 您所能做的就是将您的查询包装成一个在 GROUP BY 子句中没有 range_day 的子查询。然后按原样在外部查询中使用您的 GROUP BY 子句。但这并不合理,您正在尝试做的事情。你应该描述你想要什么以及为什么。

标签: mysql sql group-by


【解决方案1】:

不确定您要做什么。但是您可以在 GROUP BY 子句中将查询包装到不带 range_day 的子查询中。然后在外部查询中使用您的 GROUP BY 子句。

SELECT  SUM(score) score,
    type,
    context, -- WARNING! Not listed in group by clause
    post_id,
    table_code,
    comment_id,
    MIN(seen) seen,
    MAX(d_t) d_t,
    range_day
FROM (
    SELECT  SUM(score) score,
        MAX(id) as id,
        type,
        context, -- WARNING! Not listed in group by clause
        post_id,
        e.table_code,
        comment_id,
        MIN(seen) seen,
        MAX(date_time) d_t,
        (CASE   WHEN FROM_UNIXTIME(MAX(date_time)) >= CURDATE() THEN 'today'
            WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
            WHEN FROM_UNIXTIME(MAX(date_time)) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
            ELSE 'in last month'
        END) as range_day
    FROM `events` e
    WHERE e.id IN ($ids)
    GROUP BY type, post_id, e.table_code, comment_id
) sub
GROUP BY type, post_id, table_code, comment_id, range_day
ORDER BY seen, MAX(d_t) desc, MAX(id) desc

但是 - 您选择没有聚合的 context,它没有在 GROUP BY 子句中列出。因此,您将从组中获得一些“随机”值。在严格模式下查询会失败。

【讨论】:

  • 您已经在内部和外部查询的GROUP BY 子句中使用了range_day
  • @stack - 抱歉,我确定,我已经删除了 :-) - 你可能会在测试时发现一些其他错误。我没有数据/模式来测试它。
【解决方案2】:

您对range_day 的定义并不完全合理。为什么它使用MAX()?最多什么?

使查询正常工作的一种自然方法是从定义中删除MAX()

SELECT SUM(score) score, type, context, post_id, e.table_code, comment_id,
       MIN(seen) as seen, MAX(date_time) as d_t,
       (CASE WHEN FROM_UNIXTIME(date_time) >= CURDATE() THEN 'today'
             WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 DAY) THEN 'yesterday'
             WHEN FROM_UNIXTIME(date_time) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) THEN 'in last week'
            ELSE 'in last month'
        END) as range_day
FROM `events` e
WHERE e.id IN ($ids)
GROUP BY type, post_id, e.table_code, comment_id, range_day
ORDER BY seen, MAX(date_time) desc, MAX(e.id) desc;

更多cmets:

  • IN ($ids) 可能不符合您的预期。变量$ids 被视为单个值,因此这等效于e.di = $ids
  • 如果这不能满足您的要求,那么您可能希望 MAX() 处于其他聚合级别。这将需要一个额外的子查询。

【讨论】:

  • “Max of what?” 当几行加在一起时,我想要date_time 的 MAX。我的意思是当SUM() 聚合一些行时,我需要使用这些行中最大的date_time
  • 奇怪..您的查询按预期工作..但我确定它不应该!我真的不知道它是如何工作的。
  • @stack 问题在于,在您现有的查询中,应该从哪些行中提取最大值尚不清楚。通常它是每组分组值中行之间的值的最大值;但是您的分组间接包含 max 表达式,因此您要求为每个最大值提供 max ,这意味着分组的两个阶段。
【解决方案3】:

首先,你的问题...

您不能GROUP BY 聚合。注意range_day 中的MAX()。您的GROUP BY应该包括SELECT 中的所有非聚合项。 context 丢失,可能会导致后续版本出错。

那么还有一个问题……

         MIN(seen) seen,
         MAX(d_t) d_t,
...
ORDER BY seen,
         MAX(d_t) desc

注意到不一致了吗?模棱两可? seen(在ORDER BY中)应该是原来的seen,还是别名seen,意思是MIN(seen)d_t 也一样?

当您以后需要引用它时,请始终尽量避免使用与列名拼写相同的别名。在WHERE中,必须是列名;在ORDER BYHAVING 中,是别名。

所以,我认为,这是错误的:MAX(d_t) descORDER BY

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-01
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2012-11-23
    • 2019-10-03
    相关资源
    最近更新 更多