mySQL Left Join для нескольких таблиц с условиями - PullRequest
2 голосов
/ 16 января 2011

У меня проблема.У меня есть 4 таблицы:

Invoice_Payment, Invoice, Client и Calendar

По сути, у меня есть следующий запрос, который работает хорошо, за исключением месяцев без date_due, которые не возвращаются.IE будут возвращены только месяцы с date_due.

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

База данных: http://oberto.co.nz/jInvoice.txt

Ожидаемый результат: мой текущий запрос, приведенный ниже, выдаст что-то вроде:

month       total
August      5
September   0
October  196
November  205
December  214
January  229

Обратите внимание, как сентябрьне возвращается?Это потому, что таблица Invoice_Payment не имеет записи date_due

Я думаю, что мне нужно использовать левое соединение и присоединиться к таблице календаря с помощью чего-то вроде: LEFT JOIN Calendar ON Invoice_Payments.date_paid = Calendar.date_field.Но мне не повезло

SELECT MONTHNAME(Invoice_Payments.date_paid) as month, SUM(Invoice_Payments.paid_amount) AS total
FROM Invoice, Client, Invoice_Payments
WHERE Client.registered_id = 1
AND Client.id = Invoice.client_id
And Invoice.id = Invoice_Payments.invoice_id
AND date_paid IS NOT NULL
GROUP BY YEAR(Invoice_Payments.date_paid), MONTH(Invoice_Payments.date_paid)

Любая помощь приветствуется.

Ответы [ 3 ]

4 голосов
/ 16 января 2011

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

Create Table Calendar
(
    [Date] not null Primary Key
)

Ваш запрос может выглядеть так (где X и Y представляют дату начала и окончания диапазона, в котором вы исследуете):

Select Year(C.Date), MonthName(C.Date) As Month
    , Coalesce(Sum(IP.paid_amount),0) As Total
From Calendar As C
    Left Join (Invoice As I
        Join Client As C1
            On C1.id = I.client_id
                And C.registered_id = 1
        Join Invoice_Payments As IP
            On IP.Invoice_id = I.Id)
        On IP.date_paid = C.date
Where C.Date Between X and Y
Group By Year(C.Date), MonthName(C.Date)

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

Select Year(C.Date), MonthName(C.Date) As Month
    , Coalesce(Sum(Z.paid_amount),0) As Total
From Calendar As C
    Left Join   (
                Select IP.date_paid, IP.paid_amount
                From Invoice As I
                        Join Client As C1
                            On C1.id = I.client_id
                                And C.registered_id = 1
                        Join Invoice_Payments As IP
                            On IP.Invoice_id = I.Id
                ) As Z
        On Z.date_paid = C.date
Where C.Date Between X and Y
Group By Year(C.Date), MonthName(C.Date)
1 голос
/ 11 августа 2011

Я столкнулся с подобной проблемой и решил ее, переместив не календарные табличные условия из предложения WHERE в соединение.См. Мое полное объяснение здесь: https://gist.github.com/1137089

В вашем случае вам нужно будет разделить из таблицы table1, table2, table3 на левое соединение таблицы table1 на x = y и т. Д ...

0 голосов
/ 16 января 2011

Я бы определенно определил все ваши объединения для удобства чтения.

Простой пример внешнего объединения, сохраняющего все строки в первой таблице, заполняя все недостающие столбцы во второй таблице нулями:

select column1,
from table1
left outer join table2
  on table1.key = table2.key

Предполагая, что таблица Календаря является причиной потери данных, вот пример вашего запроса:

SELECT MONTHNAME(Invoice_Payments.date_paid) as month,
       SUM(Invoice_Payments.paid_amount)
FROM Invoice
JOIN Client
  ON Client.id = Invoice.client_id
 AND Client.registered_id = 1
JOIN Invoice_Payments
  ON Invoice_Payments.invoice_id = Invoice.id
LEFT OUTER JOIN Calendar
  ON Calendar.key = #yourothertable#.key    
WHERE date_paid IS NOT NULL
GROUP BY YEAR(Invoice_Payments.date_paid), MONTH(Invoice_Payments.date_paid)

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...