【问题标题】:Use Sub query result in arithmetic calculation在算术计算中使用子查询结果
【发布时间】:2014-07-04 21:45:21
【问题描述】:

我有一个包含子查询的查询。子查询返回一个COUNT() 值。我想显示这个计数,然后在基本算术计算中使用它(从查询返回的另一列中减去它)。

这是查询:

SELECT DISTINCT
    scw.SUBCOUNCIL_ID AS 'Sub Council',
    eiw.WARD_ID AS 'Ward',
    ess.DESCRIPTION AS 'Sector',
    essg.NO_OF_SEATS AS 'Sector Seats',
    (SELECT
        COUNT(in_en.NOMINATION_ID)
     FROM
        ELEC_NOMINATIONS in_en
        INNER JOIN ELEC_INTEREST_WARD in_eiw ON in_en.INTEREST_WARD_ID = in_eiw.INTEREST_WARD_ID
        INNER JOIN ELEC_SPEAKER_SECTOR in_ess ON in_eiw.SPEAKER_SECTOR_ID = in_ess.SPEAKER_SECTOR_ID
        INNER JOIN WARD in_w ON in_eiw.WARD_ID = in_w.WARD_ID
        INNER JOIN SUBCOUNCILWARD in_scw ON in_w.WARD_ID = in_scw.WARD_ID
     WHERE
        in_en.ELECTED = 1
        AND in_scw.SUBCOUNCIL_ID = scw.SUBCOUNCIL_ID
        AND in_eiw.WARD_ID = eiw.WARD_ID
        AND in_ess.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID) AS 'Elected',
    (essg.NO_OF_SEATS - "USE SUB-QUERY VALUE HERE") AS 'Vacant'
FROM
    ELEC_NOMINATIONS en
    JOIN PERSON p ON p.PERSON_ID = en.PERSON_ID
    INNER JOIN ELEC_VACANCY ev ON en.VACANCY_ID = ev.VACANCY_ID
    INNER JOIN ELEC_INTEREST_WARD eiw ON en.INTEREST_WARD_ID = eiw.INTEREST_WARD_ID
    INNER JOIN WARD w ON eiw.WARD_ID = w.WARD_ID
    INNER JOIN SUBCOUNCILWARD scw ON w.WARD_ID = scw.WARD_ID
    INNER JOIN ELEC_SPEAKER_SECTOR_GROUP essg ON ev.VACANCY_ID = essg.VACANCY_ID
    INNER JOIN ELEC_SECTOR_GROUP_SECTORS esgs ON essg.SPEAKER_GROUP_SECTOR_ID = esgs.SPEAKER_GROUP_SECTOR_ID
    INNER JOIN ELEC_SPEAKER_SECTOR ess ON esgs.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID
WHERE
    scw.SUBCOUNCIL_ID = 15
GROUP BY
    scw.SUBCOUNCIL_ID,
    eiw.WARD_ID,
    ess.SPEAKER_SECTOR_ID,
    en.PERSON_ID,
    p.FULLNAMES,
    p.SURNAME,
    en.REJECTED,
    ev.SEAT_TYPE,
    ev.TOTAL_SEATS,
    essg.NO_OF_SEATS,
    eiw.INTEREST_WARD_ID,
    eiw.WARD_ID,
    ess.DESCRIPTION

我想从“Sector Seats”列中减去计数(名为“Elected”)并将其显示为“Vacant”。如果我将整个子查询放在我想要做减法的地方,它会完美地工作,但我不想这样做。


编辑:我通过结合提供的 2 个答案使用的解决方案:

SELECT DISTINCT
    scw.SUBCOUNCIL_ID AS [Sub Council],
    eiw.WARD_ID AS [Ward],
    ess.DESCRIPTION AS [Sector],
    essg.NO_OF_SEATS AS [Sector Seats],
    ISNULL(elec.Elected, 0) AS [Elected],
    essg.NO_OF_SEATS - ISNULL(elec.Elected, 0) AS [Vacant]
FROM
    ELEC_NOMINATIONS en
    JOIN PERSON p ON p.PERSON_ID = en.PERSON_ID
    INNER JOIN ELEC_VACANCY ev ON en.VACANCY_ID = ev.VACANCY_ID
    INNER JOIN ELEC_INTEREST_WARD eiw ON en.INTEREST_WARD_ID = eiw.INTEREST_WARD_ID
    INNER JOIN WARD w ON eiw.WARD_ID = w.WARD_ID
    INNER JOIN SUBCOUNCILWARD scw ON w.WARD_ID = scw.WARD_ID
    INNER JOIN ELEC_SPEAKER_SECTOR_GROUP essg ON ev.VACANCY_ID = essg.VACANCY_ID
    INNER JOIN ELEC_SECTOR_GROUP_SECTORS esgs ON essg.SPEAKER_GROUP_SECTOR_ID = esgs.SPEAKER_GROUP_SECTOR_ID
    INNER JOIN ELEC_SPEAKER_SECTOR ess ON esgs.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID
    LEFT JOIN
    (SELECT
        in_scw.SUBCOUNCIL_ID, 
        in_eiw.WARD_ID, 
        in_ess.SPEAKER_SECTOR_ID ,
        COUNT(in_en.NOMINATION_ID) AS [Elected]
    FROM
        ELEC_NOMINATIONS in_en
        INNER JOIN ELEC_INTEREST_WARD in_eiw ON in_en.INTEREST_WARD_ID = in_eiw.INTEREST_WARD_ID
        INNER JOIN ELEC_SPEAKER_SECTOR in_ess ON in_eiw.SPEAKER_SECTOR_ID = in_ess.SPEAKER_SECTOR_ID
        INNER JOIN WARD in_w ON in_eiw.WARD_ID = in_w.WARD_ID
        INNER JOIN SUBCOUNCILWARD in_scw ON in_w.WARD_ID = in_scw.WARD_ID
    WHERE   in_en.ELECTED = 1
    GROUP BY
        in_scw.SUBCOUNCIL_ID,
        in_eiw.WARD_ID,
        in_ess.SPEAKER_SECTOR_ID) elec ON elec.SUBCOUNCIL_ID = scw.SUBCOUNCIL_ID
                                       AND elec.WARD_ID = eiw.WARD_ID
                                       AND elec.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID
    WHERE
        essg.NO_OF_SEATS > 0
        AND scw.SUBCOUNCIL_ID = 15
GROUP BY
    scw.SUBCOUNCIL_ID,
    eiw.WARD_ID,
    ess.SPEAKER_SECTOR_ID,
    essg.NO_OF_SEATS,
    ess.DESCRIPTION,
    elec.Elected

【问题讨论】:

    标签: sql sql-server sql-server-2012 subquery query-optimization


    【解决方案1】:

    您可以将相关子查询移动到APPLY,然后您可以多次引用结果:

    SELECT DISTINCT
        scw.SUBCOUNCIL_ID AS 'Sub Council',
        eiw.WARD_ID AS 'Ward',
        ess.DESCRIPTION AS 'Sector',
        essg.NO_OF_SEATS AS 'Sector Seats',
        e.Elected,
        (essg.NO_OF_SEATS - e.Elected) AS 'Vacant'
    FROM
        ELEC_NOMINATIONS en
        JOIN PERSON p ON p.PERSON_ID = en.PERSON_ID
        INNER JOIN ELEC_VACANCY ev ON en.VACANCY_ID = ev.VACANCY_ID
        INNER JOIN ELEC_INTEREST_WARD eiw ON en.INTEREST_WARD_ID = eiw.INTEREST_WARD_ID
        INNER JOIN WARD w ON eiw.WARD_ID = w.WARD_ID
        INNER JOIN SUBCOUNCILWARD scw ON w.WARD_ID = scw.WARD_ID
        INNER JOIN ELEC_SPEAKER_SECTOR_GROUP essg ON ev.VACANCY_ID = essg.VACANCY_ID
        INNER JOIN ELEC_SECTOR_GROUP_SECTORS esgs ON essg.SPEAKER_GROUP_SECTOR_ID = esgs.SPEAKER_GROUP_SECTOR_ID
        INNER JOIN ELEC_SPEAKER_SECTOR ess ON esgs.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID
        OUTER APPLY
        (   SELECT COUNT(in_en.NOMINATION_ID) AS Elected
             FROM
                ELEC_NOMINATIONS in_en
                INNER JOIN ELEC_INTEREST_WARD in_eiw ON in_en.INTEREST_WARD_ID = in_eiw.INTEREST_WARD_ID
                INNER JOIN ELEC_SPEAKER_SECTOR in_ess ON in_eiw.SPEAKER_SECTOR_ID = in_ess.SPEAKER_SECTOR_ID
                INNER JOIN WARD in_w ON in_eiw.WARD_ID = in_w.WARD_ID
                INNER JOIN SUBCOUNCILWARD in_scw ON in_w.WARD_ID = in_scw.WARD_ID
             WHERE
                in_en.ELECTED = 1
                AND in_scw.SUBCOUNCIL_ID = scw.SUBCOUNCIL_ID
                AND in_eiw.WARD_ID = eiw.WARD_ID
                AND in_ess.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID
        )  AS e
    WHERE
        scw.SUBCOUNCIL_ID = 15
    GROUP BY
        scw.SUBCOUNCIL_ID,
        eiw.WARD_ID,
        ess.SPEAKER_SECTOR_ID,
        en.PERSON_ID,
        p.FULLNAMES,
        p.SURNAME,
        en.REJECTED,
        ev.SEAT_TYPE,
        ev.TOTAL_SEATS,
        essg.NO_OF_SEATS,
        eiw.INTEREST_WARD_ID,
        eiw.WARD_ID,
        ess.DESCRIPTION
    

    还值得注意的是,使用文字作为列别名已被弃用。所以不是

    ess.DESCRIPTION AS 'Sector',
    

    您可能应该使用:

    ess.DESCRIPTION AS Sector,
    

    或者

    ess.DESCRIPTION AS [Sector]
    

    虽然我个人对reasons explained here 的偏好是:

    Sector = ess.DESCRIPTION,
    

    编辑

    我不确定您是否需要相关子查询或 APPLY,我认为您可以使用普通子查询和 JOIN 来做到这一点:

    LEFT JOIN
    (   SELECT  in_scw.SUBCOUNCIL_ID, 
                in_eiw.WARD_ID, 
                in_ess.SPEAKER_SECTOR_ID ,
                COUNT(in_en.NOMINATION_ID) AS Elected
            FROM
            ELEC_NOMINATIONS in_en
            INNER JOIN ELEC_INTEREST_WARD in_eiw ON in_en.INTEREST_WARD_ID = in_eiw.INTEREST_WARD_ID
            INNER JOIN ELEC_SPEAKER_SECTOR in_ess ON in_eiw.SPEAKER_SECTOR_ID = in_ess.SPEAKER_SECTOR_ID
            INNER JOIN WARD in_w ON in_eiw.WARD_ID = in_w.WARD_ID
            INNER JOIN SUBCOUNCILWARD in_scw ON in_w.WARD_ID = in_scw.WARD_ID
            WHERE   in_en.ELECTED = 1
            GROUP BY in_scw.SUBCOUNCIL_ID, in_eiw.WARD_ID, in_ess.SPEAKER_SECTOR_ID 
    ) e
        ON  e.SUBCOUNCIL_ID = scw.SUBCOUNCIL_ID
        AND e.WARD_ID = eiw.WARD_ID
        AND e.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID
    

    然后只需在上面的代码中引用e.ElectedAPPLY

    【讨论】:

    • 从未听说过APPLY,但那是完美的
    • 我检测到的唯一问题是计数似乎返回一个空值而不是零,但我通过使用CASE WHEN在我的问题中解决了它>
    • 使用 ISNULL(e.Elected, 0) 而不仅仅是 e.Elected。
    【解决方案2】:

    你真的需要这个子查询吗?看起来您正在加入主查询中的所有相同表,而您只是想计算“ELEC_NOMINATIONS.Elected = 1”的行数。如果是这样的话,我认为这会起作用:

    SELECT DISTINCT
        scw.SUBCOUNCIL_ID AS 'Sub Council',
        eiw.WARD_ID AS 'Ward',
        ess.DESCRIPTION AS 'Sector',
        essg.NO_OF_SEATS AS 'Sector Seats',
        SUM(case when en.Elected = 1 then 1 else 0 end) as 'Elected',
        (essg.NO_OF_SEATS - SUM(case when en.Elected = 1 then 1 else 0 end)) AS 'Vacant'
    FROM
        ELEC_NOMINATIONS en
        JOIN PERSON p ON p.PERSON_ID = en.PERSON_ID
        INNER JOIN ELEC_VACANCY ev ON en.VACANCY_ID = ev.VACANCY_ID
        INNER JOIN ELEC_INTEREST_WARD eiw ON en.INTEREST_WARD_ID = eiw.INTEREST_WARD_ID
        INNER JOIN WARD w ON eiw.WARD_ID = w.WARD_ID
        INNER JOIN SUBCOUNCILWARD scw ON w.WARD_ID = scw.WARD_ID
        INNER JOIN ELEC_SPEAKER_SECTOR_GROUP essg ON ev.VACANCY_ID = essg.VACANCY_ID
        INNER JOIN ELEC_SECTOR_GROUP_SECTORS esgs ON essg.SPEAKER_GROUP_SECTOR_ID = esgs.SPEAKER_GROUP_SECTOR_ID
        INNER JOIN ELEC_SPEAKER_SECTOR ess ON esgs.SPEAKER_SECTOR_ID = ess.SPEAKER_SECTOR_ID
    WHERE
        scw.SUBCOUNCIL_ID = 15
    GROUP BY
        scw.SUBCOUNCIL_ID,
        eiw.WARD_ID,
        ess.SPEAKER_SECTOR_ID,
        en.PERSON_ID,
        p.FULLNAMES,
        p.SURNAME,
        en.REJECTED,
        ev.SEAT_TYPE,
        ev.TOTAL_SEATS,
        essg.NO_OF_SEATS,
        eiw.INTEREST_WARD_ID,
        eiw.WARD_ID,
        ess.DESCRIPTION
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多