使用left join和group by组合同一个表中的两个查询

时间:2017-06-17 15:11:47

标签: mysql join group-by

我们说我有下表:

brand   | model   | country  | sales | year   | month
--------|---------|----------|-------|--------|-------
brand1  | model1  | US       | 10    | 2017   | 5
brand1  | model2  | US       | 11    | 2017   | 5
brand2  | model1  | US       | 5     | 2017   | 5
brand2  | model2  | US       | 18    | 2017   | 5
brand3  | model1  | US       | 8     | 2017   | 5
brand3  | model2  | US       | 12    | 2017   | 5 
brand1  | model1  | US       | 80    | 2016   | 5
brand1  | model2  | US       | 21    | 2016   | 5
brand2  | model1  | US       | 35    | 2016   | 5
brand2  | model2  | US       | 25    | 2016   | 5
brand3  | model1  | US       | 5     | 2016   | 5
brand3  | model2  | US       | 2     | 2016   | 5
brand1  | model1  | DE       | 5     | 2017   | 5
brand1  | model1  | DE       | 5     | 2017   | 4
brand3  | model2  | P        | 2     | 2016   | 5

我想显示特定国家(美国)每个品牌的总销售额,按特定年份(2017年)的特定月份(5)降序排列。这是我写的查询:

$country = str_replace ('-', '[- ]', $_GET['country']);
$year = $_GET['year'];
$month = $_GET['month'];
$previousyear = $year - 1;

$sql = "SELECT brand, SUM(sales) as sumsales
FROM `exampletable`
WHERE country REGEXP :country AND year = :year AND month = :month
GROUP BY brand ORDER BY sumsales DESC";

$stmt = $pdo->prepare($sql);
$stmt->bindParam(":country", $country);
$stmt->bindParam(":year", $year);
$stmt->bindParam(":month", $month);
$stmt->execute();
...

然后我认为在显示去年同一个月(5)同一国家/地区每个品牌的销售数据的结果中添加另一列会很不错。我尝试使用left join执行此操作但是您会注意到我开发这些类型的查询的知识并不够......:

$sql = "SELECT a.brand, SUM(a.sales) as asumsales, SUM(b.sales) as bsumsales FROM exampletable a
LEFT JOIN exampletable b on a.brand = b.brand
WHERE a.country REGEXP :country AND b.country REGEXP :country AND a.year = :year AND b.year = :previousyear AND a.month = :month AND b.month = :month
GROUP BY brand ORDER BY asumsales DESC";

预期结果:

brand   | sales US, 2017, 5 | sales US, 2016, 5
--------|-------------------|-------------------
brand2  | 23                | 60
brand1  | 22                | 101
brand3  | 20                | 7

我怎样才能得到这个结果?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

如果使用条件聚合,则可以在单个查询中执行此操作:

SELECT
    brand,
    SUM(CASE WHEN year = 2017 AND month 5 THEN sales ELSE 0 END) AS sumsales1,
    SUM(CASE WHEN year = 2016 AND month 5 THEN sales ELSE 0 END) AS sumsales2
FROM exampletable
WHERE country = 'US'
GROUP BY brand

请注意,可以将两个子查询连接到您想要的两个总和中,但这样做会更难。

答案 1 :(得分:1)

使用条件聚合。在您的情况下,这看起来像:

SELECT brand,
       SUM(CASE WHEN year = :year THEN sales ELSE 0 END) as sales_curr,
       SUM(CASE WHEN year = :year - 1 THEN sales ELSE 0 END) as sales_prev
FROM exampletable
WHERE country REGEXP :country AND
      year IN (:year, :year - 1) AND
      month = :month
GROUP BY brand
ORDER BY sales_curr DESC;