我在获取需要生成的报告的 SQL 时遇到问题。我有以下设置(等效):
- 表格
articles
(名称、manufacturer_id
等字段)。 - 表格
销售
。- FK 名为
article_id
的文章 - 一个名为
金额
的整数 日期
字段- 名为
type
的字段。我们可以假设它是一个字符串,并且可以有 3 个已知值 -'morning'
、'evening'
和'night'
- FK 名为
我想在给定开始日期和结束日期的情况下生成汇总销售报告:
+--------------+---------------+--------------+-------------+
| article_name | morning_sales | evening_sales| night_sales |
+--------------+---------------+--------------+-------------+
| article 1 | 0 | 12 | 2 |
| article 2 | 80 | 3 | 0 |
... ... ... ... ...
| article n | 37 | 12 | 1 |
+--------------+---------------+--------------+-------------+
我想尽可能高效地完成这件事。到目前为止,我已经能够生成一个查询,该查询将为我提供一种类型的销售(早上、晚上或晚上),但我无法同时为多种类型执行此操作。这可能吗?
这是我到目前为止所拥有的;它会给我指定时间段内所有文章的文章名称和早间销售额 - 换句话说,报告的前两列:
SELECT articles.name as article_name,
SUM(sales.amount) as morning_sales,
FROM "sales"
INNER JOIN articles ON articles.id = sales.articles_id
WHERE ( sales.date >= '2011-05-09'
AND sales.end_date <= '2011-05-16'
AND sales.type = 'morning'
)
GROUP BY sales.article_id
我想我可以在晚上和晚上做同样的事情,但文章会有所不同;例如,有些文章可能会在早上销售,但晚上不会销售。
- 如果我必须为每种销售类型执行 1 个请求,我该如何“混合搭配”我将获得的不同文章列表?
- 是否有更好的方法来做到这一点(也许使用某种子查询)?
同样,我可以构建一个查询,为我提供所有早间、晚间和晚间的销售情况,并按类型分组。我想我的问题是我需要执行两次 GROUP BY 才能获得此报告。如果可能的话,我不知道该怎么做。
我使用 PostgreSQL 作为我的数据库,但我想尽可能保持标准。如果有帮助,则使用它的应用程序是 Rails 应用程序。
最佳答案
幸运的是,您不需要使用数据库格式进行多次查询。这应该适合你:
SELECT
articles.name AS article_name
SUM(IF(sales.type = 'morning', sales.amount, 0.0)) AS morning_sales,
SUM(IF(sales.type = 'evening', sales.amount, 0.0)) AS evening_sales,
SUM(IF(sales.type = 'night', sales.amount, 0.0)) AS night_sales
FROM sales
JOIN articles ON sales.article_id = articles.id
WHERE
sales.date >= "2011-01-01 00:00:00"
AND sales.date < "2011-02-01 00:00:00"
GROUP BY sales.article_id
如果有其他类型,您必须在那里添加更多列,或者通过将其添加到 SELECT 子句来简单地总结其他类型:
SUM(
IF(sales.type IS NULL OR sales.type NOT IN ('morning', 'evening', 'night'),
sales.amount, 0.0
)
) AS other_sales
以上兼容MySQL。要在 Postgres 中使用它,我认为您必须将 IF
表达式更改为 CASE
expressions ,它应该看起来像这样(未经测试):
SELECT
articles.name AS article_name,
SUM(CASE WHEN sales.type = 'morning' THEN sales.amount ELSE 0.0 END) AS morning_sales,
SUM(CASE WHEN sales.type = 'evening' THEN sales.amount ELSE 0.0 END) AS evening_sales,
SUM(CASE WHEN sales.type = 'night' THEN sales.amount ELSE 0.0 END) AS night_sales
FROM sales
JOIN articles ON sales.article_id = articles.id
WHERE
sales.date >= "2011-01-01 00:00:00"
AND sales.date < "2011-02-01 00:00:00"
GROUP BY sales.article_id
关于执行两个 GROUP BY 的 SQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5942854/