在算术计算中使用子查询结果

时间:2014-05-16 12:44:32

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

我有一个包含子查询的查询。子查询返回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

2 个答案:

答案 0 :(得分:3)

您可以将相关子查询移动到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.Elected

引用上述代码中的APPLY

答案 1 :(得分:1)

你真的需要这个子查询吗?看起来您正在加入主查询中的所有相同表,并且您只是想计算" 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