2013-08-07 3 views
1

Я на самом деле немного новичок в том, как работает SQL - я всегда позволял своей ORM-ручке делать все для меня. Но в этом случае Persistent не раскрывает такую ​​функциональность, поэтому я теряюсь в том, что делать.Esqueleto/raw SQL - Сортировка запроса по результату сортировки в другой таблице?

У меня есть много-ко-многим:

+------------+ 
| Entries | 
+----+-------+ 
| id | date | 
+----+-------+ 
| 1 | Jan 1 | 
+----+-------+ 
| 2 | Jan 2 | 
+----+-------+ 
| 3 | Jan 3 | 
+----+-------+ 

+------------+ 
| Tags  | 
+------------+ 
| id | label | 
+----+-------+ 
| 1 | Apple | 
+----+-------+ 
| 2 | Boat | 
+----+-------+ 
| 3 | Car | 
+----+-------+ 

+-------------------+ 
| EntryTags   | 
+----------+--------+ 
| entry_id | tag_id | 
+----------+--------+ 
| 1  | 1  | 
+----------+--------+ 
| 1  | 2  | 
+----------+--------+ 
| 2  | 2  | 
+----------+--------+ 
| 3  | 3  | 
+----------+--------+ 

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

Тег Car последняя запись от 3 января, поэтому он идет первым. Тег Apple самая последняя запись - 2 января, но также есть тег Boat. Тем не менее, метка Apple приходит перед меткой Boat по алфавиту, так Apple является второй и Boat является третьим:

returns: 
1. Tag w/ id 3 
2. Tag w/ id 1 
3. Tag w/ id 2 

Через моих исследований я понял, что мне нужна какая-то комбинация объединений, чтобы сделать это. Однако до сих пор я нашел только ссылки для отношений «один ко многим» (сортировка тем в потоке по их последнему сообщению), и я думаю, что я их понимаю, но ни один из них не связан с этими трехсторонними объединениями для многих-ко-многим связи.

Я включаю исходный sql как возможный ответ, потому что я думаю, что я просто прошу использовать sql-способ сделать это, и хотя я использую Esqueleto для своих привязок SQL, я думаю, что как только я пойму SQL, перевод на Esqueleto будет прост. Я использую postgresql в качестве моего бэкэнд, но я бы предпочел не использовать специфичные для постгрейса вещи, потому что мои привязки для общих бэкэндов.

У кого-нибудь есть идеи, где я могу начать? С какими соединениями я должен смотреть и как я могу сортировать самую последнюю запись?

ответ

2

Другое решение:

select t.id as tag_id, t.label as tag, max(date) as date from Tags t 
join EntryTags et on t.id=et.tag_id 
join Entries e on e.id=et.entry_id 
group by t.label,t.id 
order by date desc,tag 

, которая возвращает:

tag_id tag date 
------ ----- ----- 
1  Apple jan 3 
3  Car jan 3 
2  Boat jan 2 

(В ваших данных, самая последняя запись от Apple является 3 января, а не 2 января)

Соединения в Postgres - это импликация «внутренние соединения». Если у вас могут быть теги без записей, вы захотите изменить соединения на левые соединения.

+0

Он работает, если идентификатор тега не нужен, что неясно из вопроса. –

+0

Обновлено, чтобы включить идентификатор тега. Я согласен, что желаемый результат не совсем ясен в вопросе. @justin, пожалуйста, уточните, если это не тот результат, который вам нужен. – MothOnMars

+0

достаточно, мне просто нужен способ ссылки на строку в некоторой форме или форме. Я просто не был уверен, как сортировать. Благодаря :) –

0

SQL Fiddle

Ваш образец данные не соответствуют тексту. В entrytags таблица должна быть

(1, 1), 
(1, 2), 
(2, 2), 
(2, 1), 
(3, 3); 

select id, label 
from (
    select distinct on (t.id) e.date, t.label, t.id 
    from 
     entries e 
     inner join 
     entrytags et on et.entry_id = e.id 
     inner join 
     tags t on t.id = et.tag_id 
    order by t.id, e.date desc, t.label 
) s 
order by "date" desc, label 
+0

Благодарим вас за исправление и решение :) мои извинения, хотя мой выбор для лучшего ответа был немного произвольным, так как оба решения, похоже, работали, но мне все еще не удалось заставить его работать в моем ORM, поэтому мое окончательное решение было немного сочетания обоих. –