簡體   English   中英

獲取每個父級的子級數.SQL Server 2012

[英]Get count of children from each parent.SQL Server 2012

我有2個應該相同的數據庫。 對於某些表,我需要比較並計算父母有多少個孩子,並將其與相同的數據庫進行比較。

我在獲得孩子人數的正確方法下面做了什么? 有沒有更好的辦法?

將下面的示例與一些虛設數據放在一起。帶有地址的“雇員”表比較每個雇員有多少地址。

期望的結果是我已經得到的,但是我再次想知道是否有更好的方法可以做到這一點。

所需結果:

EmployeeId  TotalAddressesA TotalAddressesB
1           4               1
2           2               5

設定:

    IF OBJECT_ID('tempdb..#EmployeeDBA') IS NOT NULL DROP TABLE #EmployeeDBA
    IF OBJECT_ID('tempdb..#EmployeeDBAddressA') IS NOT NULL DROP TABLE #EmployeeDBAddressA
    IF OBJECT_ID('tempdb..#EmployeeDBB') IS NOT NULL DROP TABLE #EmployeeDBB
    IF OBJECT_ID('tempdb..#EmployeeDBAddressB') IS NOT NULL DROP TABLE #EmployeeDBAddressB

    CREATE TABLE #EmployeeDBA
    (   [EmployeeId] [int] NOT NULL,
        [Name] [varchar](50) NULL,
        [Surname] [varchar](50) NULL
    )

    CREATE TABLE #EmployeeDBB
    (   [EmployeeId] [int] NOT NULL,
        [Name] [varchar](50) NULL,
        [Surname] [varchar](50) NULL
    )
    CREATE TABLE #EmployeeDBAddressA
    (   [EmployeeAddressId] [int] NOT NULL,
         [EmployeeId][int] NOT NULL,
        [Addresss] [varchar](50) NULL,
    )
    CREATE TABLE #EmployeeDBAddressB
    (   [EmployeeAddressId] [int] NOT NULL,
         [EmployeeId][int] NOT NULL,
        [Addresss] [varchar](50) NULL,
    )

    INSERT #EmployeeDBA (EmployeeId,Name,Surname)
    VALUES(1,'Jo','Bloggs'),(2,'Mark','Smith')

    INSERT #EmployeeDBB (EmployeeId,Name,Surname)
    VALUES(1,'Jo','Bloggs'),(2,'Mark','Smith')

    INSERT #EmployeeDBAddressA(EmployeeAddressId,EmployeeId,Addresss)
    VALUES(1,1,'Address1ForEmployee1'),
    (2,1,'Address2ForEmployee1'),
    (3,1,'Address3ForEmployee1'), 
    (4,1,'Address4ForEmployee1'),
    (5,2,'Address1ForEmployee2'),
    (6,2,'Address2ForEmployee2')      


    INSERT #EmployeeDBAddressB(EmployeeAddressId,EmployeeId,Addresss)
    VALUES(1,1,'Address1ForEmployee1'),
    (2,2,'Address1ForEmployee2'),
    (3,2,'Address2ForEmployee2'),
    (4,2,'Address3ForEmployee2'),
    (5,2,'Address4ForEmployee2'),
    (6,2,'Address5ForEmployee2')


    --BELOW IS WHAT I AM QUERYING IF IT'S BEST WAY TO FIND COUNT OF CHILDREN FOR EACH PARENT.
    ;WITH CTEA
         AS ( SELECT A.EmployeeId,
                     TotalCountA = ( 
                                          SELECT COUNT(EmployeeId)
                                          FROM #EmployeeDBAddressA b
                                          WHERE b.EmployeeId = a.EmployeeId)
              FROM #EmployeeDBA A
              GROUP BY A.EmployeeId ),
         CTEB
         AS (SELECT A.EmployeeId,
                     TotalCountB = ( 
                                          SELECT COUNT(EmployeeId)
                                          FROM #EmployeeDBAddressB b
                                          WHERE b.EmployeeId = a.EmployeeId)
              FROM #EmployeeDBB A
              GROUP BY A.EmployeeId )

        --is this the way to compare totals betwen 2 tables   

        SELECT A.EmployeeId,A.TotalCountA,B.TotalCountB
        FROM CTEA A
                LEFT JOIN CTEB B ON A.EmployeeId = B.EmployeeId
        WHERE ISNULL(A.TotalCountA, 0) <> ISNULL(B.TotalCountB, 0);


    DROP TABLE #EmployeeDBA
    DROP TABLE #EmployeeDBAddressA
    DROP TABLE #EmployeeDBB
    DROP TABLE #EmployeeDBAddressB

加入CTE時,我會使用FULL JOIN而不是LEFT JOIN來捕獲兩個表中丟失的雇員。 在具有LEFT JOIN當前變體中,如果EmployeeDBA沒有行,但是EmployeeDBB有行,則即使表不同,查詢也會返回空結果集。

在CTE中,我將聯接兩個表,而不是在子查詢中計算COUNT 不過,優化程序可能會生成相同的計划。

WITH 
CTEA
AS
(
    SELECT
        Emp.EmployeeId
        ,COUNT(Addr.EmployeeId) AS TotalCountA
    FROM
        #EmployeeDBA AS Emp
        LEFT JOIN #EmployeeDBAddressA AS Addr ON Addr.EmployeeId = Emp.EmployeeId
        -- LEFT JOIN for those Employees that don't have addresses
    GROUP BY Emp.EmployeeId
)
,CTEB
AS
(
    SELECT
        Emp.EmployeeId
        ,COUNT(Addr.EmployeeId) AS TotalCountA
    FROM
        #EmployeeDBB AS Emp
        LEFT JOIN #EmployeeDBAddressB AS Addr ON Addr.EmployeeId = Emp.EmployeeId
        -- LEFT JOIN for those Employees that don't have addresses
    GROUP BY Emp.EmployeeId
)
SELECT
    COALESCE(CTEA.EmployeeId, CTEB.EmployeeId) AS EmployeeId
    ,CTEA.TotalCountA
    ,CTEB.TotalCountB
FROM
    CTEA
    FULL JOIN CTEB ON CTEA.EmployeeId = CTEB.EmployeeId
    -- FULL JOIN to catch missing Employees in both tables
WHERE
    ISNULL(CTEA.TotalCountA, 0) <> ISNULL(CTEB.TotalCountB, 0)
;

您可以嘗試以下代碼:

   SELECT * FROM (
        SELECT EmployeeId
        FROM #EmployeeDBA
        UNION
        SELECT EmployeeId
        FROM #EmployeeDBB) AS C
    CROSS APPLY (
        SELECT COUNT(*) AS TotalCountA
        FROM #EmployeeDBAddressA WHERE EmployeeId = C.EmployeeId
    ) AS A
    CROSS APPLY (
        SELECT COUNT(*) AS TotalCountB
        FROM #EmployeeDBAddressB WHERE EmployeeId = C.EmployeeId
    ) AS B

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM