【问题标题】:SQL server average age in two different rows两个不同行中的 SQL Server 平均年龄
【发布时间】:2021-03-17 12:42:10
【问题描述】:

我有这个查询,我在其中为“女性”和“男性”创建了两列

SELECT
      ID,
      UserName,
      concat(FirstName,'  ',LastName) as Name,
      iif(substring(ID,10,1) % 2 =0,'Female', 'Male') as Gender
INTO NewUsers1
FROM   Users

现在,我想获得两性的平均年龄。我想将其分为两列,分别名为“性别”和“平均年龄”,其中一行表示“女性平均年龄”,一行表示“男性平均年龄”

我该怎么做?

年龄从列ID看出,其中数字是出生日期。

ID 

500603-4268    <-- birth year is 3rd June 1950.
500607-6521    <-- birth year is 7th June 1950.
530407-7989    <-- birth year is 4th April 1953.
530720-7675
540430-4887

【问题讨论】:

  • 请提供样本数据-@Leo

标签: sql sql-server


【解决方案1】:

这会在不丢失其他列的情况下为您提供两列的平均年龄:

select
    *
,   avg(case when Gender = 'Male' then null else age end)   over(partition by Gender)   avgAge_Female
,   avg(case when Gender = 'Female' then null else age end) over(partition by Gender)       avgAge_Male
from
    (
    select
        f1.*
        ,    datediff(
            year
            ,   cast(
                concat(
                    concat('19', left(f1.vl, 2)) 
                    , '-'
                    ,   right(left(f1.vl, 4), 2) 
                    , '-'
                    ,    right(f1.vl, 2) 
                ) 
            as date)  
            ,   getdate()
            ) age
    from
        (
        select
            ID,
            UserName,
            concat(FirstName,'  ',LastName) as Name,
            left(ID, charindex('-', ID) - 1) vl,
            iif(substring(ID,10,1) % 2 =0,'Female', 'Male') as Gender
        from Users
        ) f1
    ) g1

编辑:合并为一栏版本:

注意为了便于理解,我使用了子查询,因此它不是优化查询。

select
    h1.ID
,   h1.UserName
,   h1.Name
,   h1.Gender
,   isnull(h1.avgAge_Male, h1.avgAge_Female) avgAge_MaleOrFemale
    from
        (
        select
                *
            ,   avg(case when Gender = 'Male' then null else age end)   over(partition by Gender)   avgAge_Female
            ,   avg(case when Gender = 'Female' then null else age end) over(partition by Gender)       avgAge_Male
            from
                (
                select
                    f1.*
                    ,    datediff(
                        year
                        ,   cast(
                            concat(
                                concat('19', left(f1.vl, 2)) 
                                , '-'
                                ,   right(left(f1.vl, 4), 2) 
                                , '-'
                                ,    right(f1.vl, 2) 
                            ) 
                        as date)  
                        ,   getdate()
                        ) age
                from
                    (
                    select
                        ID,
                        UserName,
                        concat(FirstName,'  ',LastName) as Name,
                        left(ID, charindex('-', ID) - 1) vl,
                        iif(substring(ID,10,1) % 2 =0,'Female', 'Male') as Gender
                    from Users
                    ) f1
                ) g1
        ) h1

【讨论】:

  • 首选是一列“平均年龄”,每个性别各一行
  • 请查看最新版本。我已经编辑了答案。
  • 非常感谢。最后一个问题是如何隐藏列的“vl”、“avgAge_Female”和“avgAge_Male”......在这种情况下,ADD HIDDEN 似乎不起作用
  • 您可以通过编写所需的列而不是 * 来简单地更新选择部分。我已经编辑了答案,你可以检查一下。
  • 是的,明白了。感谢你的帮助。干杯
【解决方案2】:

您可以使用条件聚合:

SELECT AVG(CASE WHEN substring(ID, 10, 1) % 2 = 0 THEN AGE END) as AVG_AGE_FEMALE,
       AVG(CASE WHEN substring(ID, 10, 1) % 2 = 1 THEN AGE END) as AVG_AGE_MALE
FROM Users;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多