2015-11-24 3 views
1

У меня есть две базы данных, которые должны быть одинаковыми. Для некоторых таблиц мне нужно сравнить и подсчитать, сколько детей родитель получил и сравнить с идентичной базой данных.Получить количество детей от каждого родителя. Сервер SQL 2012

Это то, что я сделал под правильным способом, чтобы получить количество детей? Есть ли лучший способ?

Составлено ниже образца с некоторыми фиктивными данными. Таблица «Сотрудник» с адресами Сравнение количества адресов каждого сотрудника.

Желаемый результат - это то, что я уже получил, но я снова задаюсь вопросом, есть ли лучший способ сделать это.

Желаемый результат:

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 
+0

Использование 'ПОЛНЫЙ JOIN' вместо' ЛЕВЫЙ JOIN'. Кроме этого, текущий запрос кажется правильным. Это можно упростить, но это правильно. –

+0

@ VladimirBaranov спасибо за ваш комментарий Мне было интересно, как это сделать, потому что у меня не было записей в моей главной таблице? Как бы вы это упростили? Я заинтригован. Спасибо – developer9969

ответ

0

Я хотел бы использовать 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) 
; 
+0

Спасибо за вашу помощь. – developer9969

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 
Смежные вопросы