Отфильтруйте данные правого объединения в предложении where - PullRequest
1 голос
/ 08 февраля 2012

У меня есть простая структура таблицы, где каждая строка элемента имеет статус.Я ищу запрос для каждого статуса и подсчитываю, сколько элементов используют это состояние.Возможно, что не все статусы будут использоваться, поэтому мне нужно учитывать нулевые значения и счетчики нулей.

Моя структура таблиц выглядит следующим образом:

Table: Items
Id, State_id, Text, Status

Table: States
State_id, Name

Это то, что у меня есть:

SELECT   statealias1_.State_id as y0_,
         count(this_.Id)       as y1_
FROM     Items this_
         right join States statealias1_
           on this_.State_id = statealias1_.State_id
WHERE    (not (statealias1_.State_id in (5, 6, 7, 8)) 
            or statealias1_.State_id is null)
         and (this_.Status = 'InProgress' 
            or this_.Status is null)
GROUP BY statealias1_.State_id;

Этот запрос работает, когда включены все состояния (есть 8 состояний, и я исключаю вторую половину).Я не уверен, почему это не возвращает мне все состояний со счетом независимо от нуля, поскольку я, кажется, включаю нули.

Ответы [ 4 ]

2 голосов
/ 08 февраля 2012
select i.State_id as y0_, count(i.Id) as y1_
from Items i
left join States s on i.State_id = s.State_Id and i.Status = 'InProgress'
group by i.State_id
1 голос
/ 08 февраля 2012

Я думаю, что ваш SQL правильный, но у вас есть возможная логическая ошибка в вашем условии where.

У вас есть:

WHERE    (
             NOT (statealias1_.State_id in (5, 6, 7, 8)) 
             OR  statealias1_.State_id is null
)
AND      (this_.Status = 'InProgress' or this_.Status is null)

Вы имели в виду:

WHERE    NOT (
                 statealias1_.State_id in (5, 6, 7, 8) 
                 OR statealias1_.State_id is null
         )
         AND ( this_.Status = 'InProgress' or this_.Status is null )
1 голос
/ 08 февраля 2012

Вы близки, но у вас это задом наперед, как я обычно это вижу.

SELECT s.State_id, COUNT(i.Id)
FROM States AS s
LEFT OUTER JOIN Items AS i ON i.State_id = s.State_id
WHERE ...
GROUP BY s.State_id
1 голос
/ 08 февраля 2012

Я бы поменял его ... начните с ваших записей "Status" и LEFT JOIN к предварительно агрегированному набору результатов того, что вы действительно хотите включить

select
      S.State_ID,
      COALESCE( PreAgg.ICount, 0 ) as StateCount
   from
      States S
         LEFT JOIN ( select I.State_ID, count(*) as ICount
                        from Items I
                        where NOT I.State_ID IN( 5, 6, 7, 8 )
                          AND I.Status = 'InProgress'
                        group by I.State_ID ) PreAgg
            on S.State_ID = PreAgg.State_ID
...