Как считать записи после объединения нескольких таблиц в SQL - PullRequest
1 голос
/ 12 октября 2019

Мне нужно посчитать количество записей в расписании, порядке и хранить в соответствии с ecode из таблицы сотрудника, используя внутреннее соединение. Когда я использовал TestQuery, запрос считается превосходным, но когда я объединял запрос, используя внутреннее соединение в MainQuery1, я получал неверный результат (из приведенного ниже). Я обнаружил, что результат 3 из тестового запроса не соответствует друг другу и не принимает 0. Пожалуйста, помогите мне в этом. Заранее спасибо.

Мне нужно получить такой результат:

     ecode    schedulecount noordercount    salescount
      BUL-SJU-01    135    7              135
      BUL-PLA-05    1          0               0
      BUL-PLA-03    121        0              120
      BUL-MAL-03    128        3              128
      BUL-CAL-01    48         10             46
      BUL-BOC-01    111        11             111

MainQuery1: Это моя проблема

SELECT 
emp.[ecode],
COUNT(sch.[user_id]) as schedulecount,
COUNT(ord.[ecode]) as noordercount,
COUNT(sto.[ecode]) as salescount
FROM [mydb].[dbo].[employee] as emp
INNER JOIN [mydb].[dbo].[schedule] as sch 
ON  sch.[user_id] = emp.[ecode]
INNER JOIN [mydb].[dbo].[order] as ord
ON  ord.[ecode] = emp.[ecode]
INNER JOIN [mydb].[dbo].[store] as sto
ON  sto.[ecode] = emp.[ecode]
 GROUP BY 
 emp.[ecode]
 ORDER BY
 emp.[ecode] DESC;

Неверный результат:

      ecode   schedulecount noordercount    salescount
      BUL-SJU-01    127575     127575    127575
      BUL-MAL-03    49152      49152     49152
      BUL-CAL-01    22080      22080     22080
      BUL-BOC-01    135531     135531    135531

TestQuery1:

   SELECT 
emp.[ecode],
COUNT(sch.[user_id]) as schedulecount
FROM [mydb].[dbo].[employee] as emp
INNER JOIN [mydb].[dbo].[schedule] as sch 
ON  sch.[user_id] = emp.[ecode]
GROUP BY 
 emp.[ecode]
ORDER BY
 emp.[ecode] DESC;

Результат:

      ecode          schedulecount
     BUL-SJU-01       135
     BUL-PLA-05       1
     BUL-PLA-03       121
     BUL-MAL-03       128
     BUL-CAL-01       48
     BUL-BOC-01       111

TestQuery2:

  SELECT 
   emp.[ecode],
COUNT(ord.[ecode]) as schedulecount
FROM [mydb].[dbo].[employee] as emp
INNER JOIN [mydb].[dbo].[order] as ord
    ON  ord.[ecode] = emp.[ecode]
GROUP BY 
   emp.[ecode]
ORDER BY
  emp.[ecode] DESC;

Результат:

    ecode     schedulecount
    BUL-SJU-01      7
    BUL-MAL-03      3
    BUL-CAL-01      10
    BUL-BOC-01      11

TestQuery3:

SELECT 
emp.[ecode],
COUNT(sto.[ecode]) as salescount
FROM [mydb].[dbo].[employee] as emp
INNER JOIN [Z_ALI].[dbo].[M_STORE] as sto
ON  sto.[ecode] = emp.[ecode]
GROUP BY 
emp.[ecode]
ORDER BY
emp.[ecode] DESC;

Результат:

       ecode    salescount
       BUL-SJU-01   135
       BUL-PLA-03   120
       BUL-MAL-03   128
       BUL-CAL-01   46
       BUL-BOC-01   111

Ответы [ 2 ]

1 голос
/ 12 октября 2019

Альтернативный подход заключается в использовании APPLY в FROM для получения значений:

USE mydb;


SELECT emp.ecode,
       Sc.schedulecount,
       O.noordercount,
       St.salescount
FROM dbo.employee emp
     CROSS APPLY (SELECT COUNT(*) AS schedulecount
                  FROM dbo.schedule sch
                  WHERE sch.user_id = emp.ecode) Sc
     CROSS APPLY (SELECT COUNT(*) AS noordercount
                  FROM dbo.[order] ord --Generally it's a good idea to avoid Reserved Keywords for Object names
                  WHERE ord.ecode = emp.ecode) O
     CROSS APPLY (SELECT COUNT(*) AS salescount
                  FROM dbo.store sto
                  WHERE sto.ecode = emp.ecode) St
ORDER BY emp.ecode DESC;

db <> fiddle , показывающих, что результаты верны для каждого вопроса.

Хрустальный шар :

SELECT emp.ecode,
       Sc.schedulecount,
       O.noordercount,
       St.salescount
FROM dbo.employee emp
     CROSS APPLY (SELECT COUNT(*) AS schedulecount
                  FROM dbo.schedule sch
                  WHERE sch.user_id = emp.ecode) Sc
     CROSS APPLY (SELECT COUNT(*) AS noordercount
                  FROM dbo.[order] ord --Generally it's a good idea to avoid Reserved Keywords for Object names
                  WHERE ord.ecode = emp.ecode) O
     CROSS APPLY (SELECT COUNT(*) AS salescount
                  FROM dbo.store sto
                  WHERE sto.ecode = emp.ecode) St
WHERE Sc.schedulecount > 0  
   OR O.noordercount > 0
   OR St.salescount > 0
ORDER BY emp.ecode DESC;
1 голос
/ 12 октября 2019

Вы рассчитываете по нескольким измерениям. Есть несколько подходов к решению этой проблемы. Самая простая модификация - заменить count() на count(distinct):

SELECT emp.[ecode],
       COUNT(DISTINCT sch.<primary key>) as schedulecount,
       COUNT(DISTINCT ord.<primary key>) as noordercount,
       COUNT(DISTINCT sto.<primary key>) as salescount
FROM . . .

Подсчитываемый столбец является первичным ключом каждой из таблиц.

Однако это не оптимально(в целом) с точки зрения производительности. Вы также теряете ecode s, в которых отсутствуют любые значений (поскольку вы используете внутренние объединения).

Думаю, я бы порекомендовал для этого коррелированные подзапросы:

SELECT e.ecode,
       (SELECT COUNT(*)
        FROM mydb..schedule s 
        WHERE s.user_id = e.ecode
       ) as schedulecount,
       (SELECT COUNT(*)
        FROM mydb..order o 
        WHERE o.user_id = e.ecode
       ) as noordercount,
       (SELECT COUNT(*)
        FROM mydb..store s 
        WHERE s.user_id = e.ecode
       ) as salescount
FROM [mydb].[dbo].[employee] e
ORDER BY e.[ecode] DESC;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...