Предложение WHERE, приводящее к тому, что таблица пропускает правило LEFT JOIN

Я по сути пытаюсь изменить эту хранимую процедуру.

Модифицированная хранимая процедура:

CREATE PROCEDURE sp1(d1 date, d2 date, client INT(10))
    declare d datetime;

    create TEMPORARY TABLE foo (d date NOT NULL, Amount INT(10) DEFAULT 0);

    set d = d1;

    while d <= d2 do 
        insert into foo (d) values (d);
        set d = date_add(d, interval 1 day);
    end while;

    SELECT SUM(p.Amount), foo.d
    FROM foo LEFT JOIN ItemTracker_dbo.Payment ON foo.d = p.Datetime
    WHERE p.ClientId = ClientId
    GROUP BY
        foo.d;

    DROP TEMPORARY TABLE foo;
end PROCEDURE

ПРИМЕЧАНИЕ: предложение WHERE... p.ClientId = client

Я ломал свой мозг, пытаясь понять, почему он опускает нули.

после удаленияWHERE p.ClientId = client процедура стала возвращать NULL...

Почему в предложении WHERE пропущены пустые строки? Я, вероятно, неправильно понимаю, что именно LEFT JOIN является.

Как я могу пойти о фильтрации SUM(p.Amount) результаты только вернуть сумму WHERE clientId = client?

4 ответа

Решение

Это должно работать, если вы поставите все условия в LEFT JOIN состояние:

SELECT SUM(p.Amount), foo.d
FROM foo
LEFT JOIN ItemTracker_dbo.Payment p ON foo.d = p.Datetime AND p.ClientId = ClientId
GROUP BY
    foo.d;

Прежде всего, это не ваш пример кода

SELECT SUM(p.Amount), foo.d 
    FROM foo LEFT JOIN ItemTracker_dbo.Payment ON foo.d = p.Datetime 
    WHERE p.ClientId = ClientId 
    GROUP BY 
        foo.d; 

не хватает p для псевдонима для таблицы ItemTracker_dbo.Payment?? т. е. не должен читать:

SELECT SUM(p.Amount), foo.d 
    FROM foo 
       LEFT JOIN ItemTracker_dbo.Payment p
            ON foo.d = p.Datetime 
WHERE p.ClientId = ClientId 
GROUP BY foo.d; 

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

SELECT SUM(p.Amount), foo.d 
    FROM foo 
       LEFT JOIN ItemTracker_dbo.Payment p
            ON foo.d = p.Datetime 
                And p.ClientId = ClientId 
GROUP BY foo.d; 

Переместить WHERE пункт в ON пункт, как это:

SELECT SUM(p.Amount), foo.d
FROM foo LEFT JOIN ItemTracker_dbo.Payment ON foo.d = p.Datetime 
    and p.ClientId = ClientId
GROUP BY
    foo.d;

Поместив сравнение ClientId в предложение WHERE, вы эффективно перевернули LEFT JOIN обратно в INNER JOIN на ClientId,

Проблема в том, что оператор = не является NULL-безопасным в SQL. NULL = NULL ложно Вы должны использовать NULL-безопасный эквивалент, который, если я правильно помню, <=> на MySQL. Вы также можете использовать COALESCE функция или запись a=b как (a=b OR a IS NULL or b IS NULL),

Другие вопросы по тегам