2013-02-20 5 views
3

У меня есть база данных:группа, не-нулевых значений

+--+----+---------+ 
|id|name|source_id| 
+--+----+---------+ 
|11|aaaa|null 
+--+----+---------+ 
|12|bbbb|1 
+--+----+---------+ 
|13|cccc|1 
+--+----+---------+ 
|14|dddd|null 
+--+----+---------+ 
|15|eeee|2 
+--+----+---------+ 
|16|ffff|2 
+--+----+---------+ 
|17|gggg|2 
+--+----+---------+ 

я хотел бы, чтобы выбрать все записи, с исключением:

  • все записи с source_id == somevalue(not null) должны быть сгруппированы
  • Последнее сообщение с source_id == null должно существовать впоследствии

Вот результат я ожидаю:

+----+--+----+---------+ 
COUNT|id|name|source_id| 
+----+--+----+---------+ 
.....|11|aaaa|null 
+----+--+----+---------+ 
.2...|13|cccc|1 
+----+--+----+---------+ 
.....|14|dddd|null 
+----+--+----+---------+ 
.3...|17|ffff|2 
+----+--+----+---------+ 

До сих пор я сделал это (примечание: "CHANGE_COUNT" = COUNT):

SELECT *, (To_days(date_expires)-TO_DAYS(NOW())) as dayDiff, COUNT(id) AS change_count FROM mytable 
GROUP BY source_id 
HAVING dayDiff < 4 
ORDER BY date_created DESC 

Вот что я получаю:

+----+--+----+---------+ 
COUNT|id|name|source_id| 
+----+--+----+---------+ 
.2...|11|aaaa|null 
+----+--+----+---------+ 
.2...|12|bbbb|1 
+----+--+----+---------+ 
.3...|15|eeee|2 
+----+--+----+---------+ 

Как вы можете видеть результат есть 2 проблемы:

  • записи сгруппированы по первому source_id возникновения (должен быть последним (последний))
  • nulls также сгруппированы (не должны группироваться)

задача, которую я описал выше достижимо? Как мне это сделать?

Edit:

SELECT *, COUNT(id) AS change_count FROM 
(SELECT *, (To_days(date_return_due)-TO_DAYS(NOW())) as dayDiff FROM mytable 
WHERE owner_id='1' 
HAVING dayDiff < 100 
ORDER BY date_created DESC) AS newtable 
GROUP BY (CASE WHEN source_id IS NULL THEN id ELSE source_id END) 
ORDER BY (CASE WHEN source_id IS NULL THEN 1 ELSE 0 END), date_created DESC"; 
+1

Подсказка: использовать 'UNION'. О, добавьте тег Oracle, если вы используете Oracle. –

ответ

4

Я думаю, что следующий делает то, что вы хотите:

SELECT *, (To_days(date_expires)-TO_DAYS(NOW())) as dayDiff, COUNT(id) AS change_count 
FROM mytable 
GROUP BY (case when source_id is null then id else source_id end) 
HAVING dayDiff < 4 
ORDER BY (case when source_id is null then 1 else 0 end), date_created DESC 

Это делает условный group by так Исходные элементы NULL не будут сгруппированы. Затем он ставит их последним, используя логику в order by.

Я не понял, что вы имели в виду при последнем вхождении. Теперь я думаю:

SELECT coalesce(s.id, mytable.id) as id, 
     max(case when s.maxid is not null and s.maxid = myable.id then mytable.name 
       when s.maxid is null then NULL 
       else mytable.name 
      end) as name, 
     (To_days(date_expires)-TO_DAYS(NOW())) as dayDiff, COUNT(id) AS change_count 
FROM mytable left outer join 
    (select source_id, MAX(id) as maxid 
     from mytable 
     where source_id is not null 
     group by source_id 
    ) s 
    on mytable.id = s.maxid 
GROUP BY (case when source_id is null then id else source_id end) 
HAVING dayDiff < 4 
ORDER BY (case when source_id is null then 1 else 0 end), date_created DESC 

Входит в информацию из последней записи (на основе наивысшего идентификатора).

+0

все работает нормально, за исключением того, что Group by объединяется с «другой стороной» (как описано в моем сообщении: записи сгруппированы по первому вступлению source_id (должно быть последним)) – Alex

+0

@Alex. , , Я думаю, теперь у меня есть правильная логика. Я понимаю шаги.Мне сложно получить все сразу, без данных образца. –

+0

, наконец, получил его работу;) Мне удалось создать свой собственный запрос на основе вашего первого (предварительно отредактированного) ответа. Спасибо за помощь! – Alex

4

Попробуйте изменить group by быть:

GROUP BY coalesce(source_id, id) 
0

Тест

SELECT *, IFNULL (SOURCE_ID, UUID()), как unique_source ОТ имя_таблицы где (условия) GROUP BY unique_source

Смежные вопросы