【问题标题】:Subquery not working the way i want it to子查询没有按我想要的方式工作
【发布时间】:2021-12-15 12:54:20
【问题描述】:

这是我第一次在 stackoverflow 上发帖。

我想查看每个 marital_status 的每个教育级别的最低、平均和最高工资是多少。 我试过这段代码,但它只显示所有不同教育水平的最小值、平均值和最大值:

Select distinct education, (select min(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'Married' and year_birth > 1980 and income <> 0) Min_Married,
                            (select avg(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'Married' and year_birth > 1980 and income <> 0) Avg_Married,
                            (select max(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'Married' and year_birth > 1980 and income <> 0) Max_Married,
                            (select min(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'Single' and year_birth > 1980 and income <> 0) Min_Single,
                            (select avg(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'Single' and year_birth > 1980 and income <> 0) Avg_Single,
                            (select max(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'Single' and year_birth > 1980 and income <> 0) Max_Single,
                            (select min(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'together' and year_birth > 1980 and income <> 0) Min_together,
                            (select avg(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'together' and year_birth > 1980 and income <> 0) Avg_together,
                            (select max(convert(int, income))
                            from [dbo].[marketing_campaign] where marital_status = 'together' and year_birth > 1980 and income <> 0) Max_together
from [dbo].[marketing_campaign]
where  education in ('master', 'Graduation', 'phd', 'basic')
group by education
order by education desc

提前致谢!

【问题讨论】:

    标签: sql group-by subquery


    【解决方案1】:

    在您的子查询中与education 没有关联,当我怀疑您需要以下内容时,也不需要重复使用子查询:

    with i as (
        select education, 
            Iif(marital_status = 'Married' , Convert(int, income),0) Income_Married,
            Iif(marital_status = 'Single'  , Convert(int, income),0) Income_Single,
            Iif(marital_status = 'together', Convert(int, income),0) Income_Together,
        from dbo.marketing_campaign
        where education in ('master', 'Graduation', 'phd', 'basic')
        and year_birth > 1980 and income != 0
    )
    select education, 
        Min(Income_Married) Min_Married,
        Avg(Income_Married) Avg_Married,
        Max(Income_Married) Max_Married,
        Min(Income_Single) Min_Single,
        Avg(Income_Single) Avg_Single,
        Max(Income_Single) Max_Single,
        Min(Income_Together) Min_Together,
        Avg(Income_Together) Avg_Together,
        Max(Income_Together) Max_Together
    from i
    group by education
    order by education desc;
    

    【讨论】:

    • 非常感谢您的回答。我现在意识到我的解释/问题并不清楚。我进行子查询的原因是因为我想检查所有不同的婚姻状况 min、avg 和 max 作为列。 IE。我想要 9 个子查询,“单身”、“已婚”和“一起”的最小、平均和最大。
    • 我不清楚您的期望 - 上面给出的列与您的示例查询相同。如果上述内容不是您所需要的,那么提供一些示例数据并显示您想要的结果将会很有帮助。
    • 我已经更新了帖子。使用我编写的代码,输出为我提供了所有不同教育水平的相同值。例如:学历 Min_Married PhD 7500 Master 7500 Graduation 7500 Basic 7500
    • @MartinNordinSundberg 根据您编辑的问题,我已经在上面进行了修改 - 有几种方法可以有条件地 case 聚合,您也可以使用基本相同但更简洁的 inline if,并将条件案例逻辑从聚合中分离出来,使得方法更加简洁(恕我直言)。
    • 非常感谢 Stu,CTE 版本成功了!
    【解决方案2】:

    您可以简单地按照以下方式进行操作。我尝试制作与您在我的数据库中描述的相同的环境,所以希望这会对您有所帮助。

    SELECT   DISTINCT C.education,
             MIN(income) OVER(PARTITION BY education) AS MIN_Married, 
             AVG(income) OVER(PARTITION BY education) AS AVG_Married, 
             MAX(income) OVER(PARTITION BY education) AS MAX_Married 
    FROM     [dbo].[marketing_campaign] C
    WHERE    education IN ('master', 'Graduation', 'phd', 'basic')
             AND marital_status = 'Married'
             AND year_birth > 1980
    ORDER BY education DESC
    

    【讨论】:

    • 非常感谢您的回答。我现在意识到我的解释/问题并不清楚。我进行子查询的原因是因为我想检查所有不同的婚姻状况 min、avg 和 max 作为列。 IE。我想要 9 个子查询,“单身”、“已婚”和“一起”的最小、平均和最大。
    【解决方案3】:

    使用条件聚合:

    SELECT education, 
           MIN(CASE WHEN marital_status = 'Married' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Min_Married,
           AVG(CASE WHEN marital_status = 'Married' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Avg_Married,
           MAX(CASE WHEN marital_status = 'Married' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END)  Max_Married,
           MIN(CASE WHEN marital_status = 'Single' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Min_Single,
           AVG(CASE WHEN marital_status = 'Single' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Avg_Single,
           MAX(CASE WHEN marital_status = 'Single' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Max_Single,
           MIN(CASE WHEN marital_status = 'together' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Min_together,
           AVG(CASE WHEN marital_status = 'together' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Avg_together,
           MAX(CASE WHEN marital_status = 'together' AND year_birth > 1980 AND income <> 0) THEN CONVERT(INT, income) END) Max_together
    FROM [dbo].[marketing_campaign]
    WHERE education IN ('master', 'Graduation', 'phd', 'basic')
    GROUP BY education
    ORDER BY education DESC;
    

    或者,移动WHERE子句中的常用条件:

    SELECT education, 
           MIN(CASE WHEN marital_status = 'Married' THEN CONVERT(INT, income) END) Min_Married,
           AVG(CASE WHEN marital_status = 'Married' THEN CONVERT(INT, income) END) Avg_Married,
           MAX(CASE WHEN marital_status = 'Married' THEN CONVERT(INT, income) END)  Max_Married,
           MIN(CASE WHEN marital_status = 'Single' THEN CONVERT(INT, income) END) Min_Single,
           AVG(CASE WHEN marital_status = 'Single' THEN CONVERT(INT, income) END) Avg_Single,
           MAX(CASE WHEN marital_status = 'Single' THEN CONVERT(INT, income) END) Max_Single,
           MIN(CASE WHEN marital_status = 'together' THEN CONVERT(INT, income) END) Min_together,
           AVG(CASE WHEN marital_status = 'together' THEN CONVERT(INT, income) END) Avg_together,
           MAX(CASE WHEN marital_status = 'together' THEN CONVERT(INT, income) END) Max_together
    FROM [dbo].[marketing_campaign]
    WHERE education IN ('master', 'Graduation', 'phd', 'basic')
      AND year_birth > 1980 AND income <> 0
    GROUP BY education
    ORDER BY education DESC;
    

    【讨论】:

    • 感谢 Forpas 的回答,效果很好!
    • @MartinNordinSundberg,它是在您接受的答案被编辑之前发布的。
    猜你喜欢
    • 1970-01-01
    • 2011-04-18
    • 2023-03-15
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 2023-03-05
    相关资源
    最近更新 更多