繁体   English   中英

MySQL - GROUP BY 不使用多个 CASE WHEN 语句

[英]MySQL - GROUP BY not working with multiple CASE WHEN statements

我正在使用 Kickstarter 数据库开发数据库,我正在尝试:

  1. 定义短、中长和长广告系列
  2. 查看每次竞选活动筹集了多少资金
  3. 将不同的货币兑换成美元

我的原始代码如下:

 SELECT 
    CASE 
        WHEN DATEDIFF(campaign.deadline,campaign.launched)<=30 THEN 'Short Campaign' 
        WHEN DATEDIFF(campaign.deadline,campaign.launched)>30 AND DATEDIFF(campaign.deadline,campaign.launched)<=60 THEN 'Mid-lengthed Campaign'
        ELSE 'Long Campaign'
        END AS 'Campaign Length',
    CASE 
        WHEN currency.name='GBP' THEN ROUND(SUM(campaign.pledged)*0.80,2)
        WHEN currency.name='CAD' THEN ROUND(SUM(campaign.pledged)*1.36)
        WHEN currency.name='AUD' THEN ROUND(SUM(campaign.pledged)*1.43)
        WHEN currency.name='NOK' THEN ROUND(SUM(campaign.pledged)*9.28)
        WHEN currency.name='EUR' THEN ROUND(SUM(campaign.pledged)*0.87)
        WHEN currency.name='MXN' THEN ROUND(SUM(campaign.pledged)*22.48)
        WHEN currency.name='SEK' THEN ROUND(SUM(campaign.pledged)*0.04)
        WHEN currency.name='NZD' THEN ROUND(SUM(campaign.pledged)*1.53)
        WHEN currency.name='CHF' THEN ROUND(SUM(campaign.pledged)*0.94)
        WHEN currency.name='DKK' THEN ROUND(SUM(campaign.pledged)*6.52)
        WHEN currency.name='HKD' THEN ROUND(SUM(campaign.pledged)*7.75)
        WHEN currency.name='SGD' THEN ROUND(SUM(campaign.pledged)*1.39)
        WHEN currency.name='JPY' THEN ROUND(SUM(campaign.pledged)*107.11)
        ELSE ROUND(SUM(campaign.pledged),2)
    END AS 'Amount Raised'
FROM campaign
LEFT JOIN currency ON currency.id=campaign.currency_id
GROUP BY `Campaign Length`;

我期待的结果是:

Campaign Length.      ---- Amount Raised
Short Campaign.       ---- XXXXXXXXXXXXX
Mid-Lengthed Campaign ---- XXXXXXXXXXXXX
Long Campaign.        ---- XXXXXXXXXXXXX

其中XXXXXX为折算后的质押金额之和。 原始代码显示:

Error Code: 1055. Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'ks_data.currency.name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

所以我通过添加额外的 GROUP BY 即兴创作,在意识到我不能 GROUP BY Amount Raised之后:

 SELECT 
    CASE 
        WHEN DATEDIFF(campaign.deadline,campaign.launched)<=30 THEN 'Short Campaign' 
        WHEN DATEDIFF(campaign.deadline,campaign.launched)>30 AND DATEDIFF(campaign.deadline,campaign.launched)<=60 THEN 'Mid-lengthed Campaign'
        ELSE 'Long Campaign'
        END AS 'Campaign Length',
    CASE 
        WHEN currency.name='GBP' THEN ROUND(SUM(campaign.pledged)*0.80,2)
        WHEN currency.name='CAD' THEN ROUND(SUM(campaign.pledged)*1.36)
        WHEN currency.name='AUD' THEN ROUND(SUM(campaign.pledged)*1.43)
        WHEN currency.name='NOK' THEN ROUND(SUM(campaign.pledged)*9.28)
        WHEN currency.name='EUR' THEN ROUND(SUM(campaign.pledged)*0.87)
        WHEN currency.name='MXN' THEN ROUND(SUM(campaign.pledged)*22.48)
        WHEN currency.name='SEK' THEN ROUND(SUM(campaign.pledged)*0.04)
        WHEN currency.name='NZD' THEN ROUND(SUM(campaign.pledged)*1.53)
        WHEN currency.name='CHF' THEN ROUND(SUM(campaign.pledged)*0.94)
        WHEN currency.name='DKK' THEN ROUND(SUM(campaign.pledged)*6.52)
        WHEN currency.name='HKD' THEN ROUND(SUM(campaign.pledged)*7.75)
        WHEN currency.name='SGD' THEN ROUND(SUM(campaign.pledged)*1.39)
        WHEN currency.name='JPY' THEN ROUND(SUM(campaign.pledged)*107.11)
        ELSE ROUND(SUM(campaign.pledged),2)
    END AS 'Amount Raised'
FROM campaign
LEFT JOIN currency ON currency.id=campaign.currency_id
GROUP BY `Campaign Length`,currency.id;

但结果并没有按照我的意图进行分组:

Campaign Length.      ---- Amount Raised
Short Campaign.       ---- XXXXXXXXXXXXX
Mid-Lengthed Campaign ---- XXXXXXXXXXXXX
Long Campaign.        ---- XXXXXXXXXXXXX
Mid-Lengthed Campaign ---- XXXXXXXXXXXXX
Mid-Lengthed Campaign ---- XXXXXXXXXXXXX
Short Campaign.       ---- XXXXXXXXXXXXX

我尝试了很多方法,但找不到解决方案

您需要在聚合 function 中移动货币名称上的case表达式:

SELECT 
    CASE 
        WHEN DATEDIFF(ca.deadline,ca.launched) <= 30 THEN 
            'Short Campaign' 
        WHEN DATEDIFF(ca.deadline,ca.launched) <= 60 
            THEN 'Mid-lengthed Campaign'
        ELSE 'Long Campaign'
    END AS campaign_length,
    ROUND(SUM(
        ca.pledged 
        * CASE cu.name
            WHEN 'GBP' THEN 0.8
            WHEN 'CAD' THEN 1.36
            WHEN 'AUD' THEN 1.43
            ...
            ELSE 1
        END
    ), 2) as amount_raised
FROM campaign ca
LEFT JOIN currency cu ON cu.id = ca.currency_id 
GROUP BY campaign_length;

其他需要注意的事项:

  • 不要对列标识符使用单引号 - 它们用于文字字符串(MySQL 需要反引号); 事实上,使用不需要引用的标识符更简单

  • 两种case表达式都可以简化,如上所示; 在第一个中,不需要检查第二个分支中的活动持续时间是否大于 30(第一个分支已经陷阱); 在第二个中,您可以使用短路形式而不是在每个分支中重复列名

  • 表别名使查询更易于编写和阅读

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM