СЛЕДУЕТ ПРИСОЕДИНИТЬСЯ СЧИТАЕТСЯ, ЧТО ПРИЗНАВАЕТ ДИАПАЗОНЫ? - PullRequest
0 голосов
/ 12 марта 2019

У меня есть запрос, переписанный для объединения таблиц, а не выполнения подзапросов, так как мне нужно просмотреть около 10 цифр, и у 10 подзапросов возникает небольшая проблема с производительностью.

Имена таблиц истолбцы изменены для простоты *

Запрос ранее сделал это:

SELECT t1.col1, t1.col2, t1.col3, 
(SELECT COUNT(j1.j_id) FROM jointable1 as j1 WHERE t1.t_employee_id = j1.j_employee_id
    AND t1.t_week_ending = j1.j_week_ending AND j1.j_reason <> 'DNC') as col4,
(SELECT COUNT(j2.j_id) FROM jointable1 as j2 WHERE t1.t_employee_id = j2.j_employee_id
    AND t1.t_week_ending = j2.j_week_ending) as col5
FROM table1 as t1
GROUP BY t1.col1, t1.col2, t1.col3;

Я переписал это так:

SELECT t1.col1, t1.col2, t1.col3, COUNT(j1.j_id) as col4, COUNT(j2.o_id) as col5
FROM table1 as t1
LEFT JOIN jointable1 as j1 ON (t1.t_employee_id = j1.j_employee_id
    AND t1.t_week_ending = j1.j_week_ending)
    AND j1.j_reason = <> 'DNC'
GROUP BY t1.col1, t1.col2, t1.col3;

Проблема в том,что значения, которые возвращаются для col4 и col5 в верхнем примере, в порядке.Допустим, они возвращают 7 и 8.

+------+------+------+------+--+
| col1 | col2 | col3 | col4 |  |
+------+------+------+------+--+
|    1 |    0 |    0 |   34 |  |
|    0 |    3 |    3 |    9 |  |
|    7 |    1 |    0 |    2 |  |
|    3 |    2 |    2 |    9 |  |
|    4 |    1 |    0 |    4 |  |
|    1 |   11 |    1 |    4 |  |
|    5 |    2 |    5 |   21 |  |
|    2 |    3 |    0 |    3 |  |
|    2 |    3 |    0 |    2 |  |
+------+------+------+------+--+

Но в нижнем запросе они возвращаются в квадрате или умножаются на себя.Таким образом, 7 становится 49, а 8 становится 64.

+------+------+------+------+--+
| col1 | col2 | col3 | col4 |  |
+------+------+------+------+--+
|    1 |    0 |    0 | 1156 |  |
|    0 |    3 |    3 |   81 |  |
|    7 |    1 |    0 |   16 |  |
|    3 |    2 |    2 |   81 |  |
|    4 |    1 |    0 |   16 |  |
|    1 |   11 |    1 |   16 |  |
|    5 |    2 |    5 |  441 |  |
|    2 |    3 |    0 |    9 |  |
|    2 |    3 |    0 |    4 |  |
+------+------+------+------+--+

Я не могу сказать, является ли это ЛЕВОЕ СОЕДИНЕНИЕ или что-то отсутствует в функции GROUP BY, но любая помощь в исправлении будет большой, или любая помощь в переписывании в еще более эффективный способ была бы также полезной.

Ответы [ 4 ]

2 голосов
/ 12 марта 2019

Количество строк может увеличиться, если у вас есть несколько совпадающих записей в вашем JOINS, что может дать вам неверные результаты при использовании агрегатной функции, такой как COUNT. Вам нужно использовать COUNT с DISTINCT, как показано ниже.

 SELECT   t1.col1, 
          t1.col2, 
          t1.col3, 
          Count(DISTINCT j1.j_id) AS col4, 
          Count(DISTINCT j1.o_id) AS col5 
FROM      table1                  AS t1 
LEFT JOIN jointable1              AS j1 
ON        t1.t_employee_id = j1.j_employee_id 
AND       t1.t_week_ending = j1.j_week_ending 
AND       j1.j_reason = <> 'DNC' 
GROUP BY  t1.col1, 
          t1.col2, 
          t1.col3;

Примечание: В вашем запросе вы используете псевдоним j2, который нигде не задан, вам необходимо исправить его соответствующим образом.

1 голос
/ 12 марта 2019

Попробуйте написать запрос с помощью outer apply.Это будет более эффективным.Кроме того, вы не получите правильные значения для col5 из вашего второго запроса.Вам нужно количество строк, где j_reason не равно DNC для col4, и все они для col5.

SELECT  t1.col1, t1.col2, t1.col3, c4.col4, c5.col5
FROM    table1 as t1
OUTER APPLY
(
    SELECT  COUNT(j1.j_id) col4
    FROM    jointable1 as j1 
    WHERE   t1.t_employee_id = j1.j_employee_id
    AND     t1.t_week_ending = j1.j_week_ending 
    AND     j1.j_reason <> 'DNC'
)c4
OUTER APPLY
(
    SELECT  COUNT(j2.j_id) col5
    FROM    jointable1 as j2 
    WHERE   t1.t_employee_id = j2.j_employee_id
    AND     t1.t_week_ending = j2.j_week_ending
)c5
0 голосов
/ 12 марта 2019
SELECT 
    t1.col1,
    t1.col2,
    t1.col3, 
    cnt.col4,
    cnt.col5
FROM table1 as t1
    LEFT JOIN (
        SELECT j1.j_employee_id
            ,j1.j_week_ending
            ,SUM(CASE WHEN j1.j_reason <> 'DNC' AND j1.j_id IS NOT NULL THEN 1 ELSE 0 END) as col4
            ,COUNT(j1.j_id) as col5
        FROM jointable1 as j1
        GROUP BY j1.j_employee_id, j1.j_week_ending
    ) cnt ON t1.t_employee_id = cnt.j_employee_id
        AND t1.t_week_ending = cnt.j_week_ending
GROUP BY t1.col1, t1.col2, t1.col3;
0 голосов
/ 12 марта 2019

Лучше выполнить подсчет в подзапросах, которые могут их обработать для всех комбинаций, а затем присоединиться к этим результатам, теперь вы знаете, что будете присоединяться только к одной строке из каждого подзапроса.

Вы сталкиваетесь с проблемами, когда вы объединяете несколько столов одним способом.Если у вас есть две ассоциации 1-2 и вы присоединяетесь к обеим, вы получите 4 строк, а не 2 .

SELECT t1.col1, t1.col2, t1.col3, j1.Cnt, /* same for j2 */
FROM table1 as t1
LEFT JOIN (select j_employee_id,j_week_ending,COUNT(j_id) AS Cnt
     from jointable1
     where j_reason <> 'DNC'
     group by j_employee_id,j_week_ending) j1
ON (t1.t_employee_id = j1.j_employee_id
    AND t1.t_week_ending = j1.j_week_ending)
/* Same again for j2 */
/* Don't need GROUP BY out here at all now? */
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...