高级mysql分组问题 - 脑力激荡

时间:2012-06-26 11:08:26

标签: mysql sum grouping

去年我一直在大量使用stackoverflow - 一个很棒的贡献者来源。现在是时候请求帮助了。

设置正常: 订单,订单文章和文章

我想获得去年销售的文章总数,但仅限于最佳的5周

别介意WEEK功能和UNIXTIME-blah等等 - 我已经覆盖了它。我的问题是,如果不诉诸存储过程或函数,是否可行。

我为每周和文章的摘要创建了一个子查询,并按降序总和对结果进行排序。现在 - 我只需要将查询限制为5.简单,但我还必须在ArticleID上过滤结果,因为我在子查询中,我没有访问外部的ArticleID,它没有帮助加入结果 - 为时已晚; - )

语法(很难理解没有实际的sql,对吧......?)

SELECT a.ID, [more fields], omg.total
FROM Articles AS a
LEFT JOIN
(
    SELECT weeklytotals.articleID, weeklytotals.total
    FROM
    (
        SELECT SUM(ra.quantity) AS total, ra.articleID AS articleID
        FROM OrderArticles ra
        INNER JOIN Orders r
            ON ra.orderID = r.ID
        WHERE r.timeCreated >= UNIX_TIMESTAMP('2011-06-30')
        GROUP BY ra.articleID, WEEK(FROM_UNIXTIME(r.timeCreated))
        ORDER BY SUM(ra.quantity) DESC
    ) AS weeklytotals
    WHERE omg.articleID = a.ID --<-- THIS IS NOT WORKING BUT NECESSARY!
    LIMIT 0, 5
) AS omg
ON omg.articleID = a.ID
WHERE a.isEnabled = 1 --more WHERE-thingys 

这里返回前5篇文章,并将它们与正确的文章联系起来。耶。

我遗漏了SUM函数(可以进入omg-SELECT)。

你知道吗?我明白自己想要什么吗?是的,我们当然可以!

提前完成。

编辑:条件已经改变 - 这使我的生活更轻松,但我仍然想知道是否有问题的解决方案。

1 个答案:

答案 0 :(得分:1)

如果您要求omg子查询使用a表中的数据,请将其放入SELECT部分而不是FROM部分。使用mysql文档中的术语,您希望correlated subquery的结果在外部结果集中显示为scalar operand

您写过关于总和的兴趣,即每篇文章只有一个数字,尽管您从示例查询中遗漏了SUM。我的方法依赖于这笔钱,如果你真的需要最好的五周中每一个的不同价值,那么它可能会以一种糟糕的方式打破。

SELECT a.ID, [more fields], IFNULL(SUM(
    (
        SELECT SUM(ra.quantity) AS total
        FROM OrderArticles ra
        INNER JOIN Orders r
           ON ra.orderID = r.ID
        WHERE ra.articleID = a.ID -- <-- reference a.ID here
          AND r.timeCreated >= UNIX_TIMESTAMP('2011-06-30')
        GROUP BY WEEK(FROM_UNIXTIME(r.timeCreated))
        ORDER BY SUM(ra.quantity) DESC
        LIMIT 0, 5
    )), 0) AS total
FROM Articles AS a
WHERE a.isEnabled = 1 --more WHERE-thingys 
GROUP BY a.ID

我在这里没有说任何表现。以这种方式放置子查询,它将对结果集的每一行执行。因此,如果您有大量文章,实际使用可能会太慢。但如果发生这种情况,我怀疑存储过程或类似的技巧会更好。

编辑:我发现我的原始建议,使用嵌套两层深度的subquerys,不允许访问最里面的子查询使用最外层的列。但是玩弄this on sqlfiddle我也发现可以安全地将子查询的结果传递给sum,从而避免了一级嵌套。因此,上面的代码实际上已经由MySQL服务器检查和执行,因此应该按预期工作。