Esqueleto / raw SQL - 按另一个表上的排序结果对查询进行排序?

时间:2013-08-07 23:21:40

标签: sql haskell yesod esqueleto

我实际上对SQL的工作方式有点新意 - 我总是让我的ORM为我处理一切。但是在这种情况下,Persistent并没有公开这种功能,所以我很想做什么。

我有多对多的关系:

+------------+
| 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的最新条目是1月3日,所以它是第一个。 标记Apple的最新条目是1月2日,但标记Boat也是如此。但是,标签Apple按字母顺序排在标记Boat之前,因此Apple为第2,Boat为第3:

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

通过我的研究,我发现我需要某种联接组合才能做到这一点。然而到目前为止,我只发现了一对多关系的问题(通过最近的帖子在一个帖子中对主题进行排序),我想我理解它们,但没有涉及多对多的这些三向连接关系。

我包含原始sql作为一个可能的答案,因为我认为我真的只是要求sql方式来做,即使我使用Esqueleto进行我的SQL绑定,我认为一旦我理解了SQL,Esqueleto的翻译将很简单。我使用postgresql作为我的后端,但我宁愿不使用postgres特定的东西,因为我的绑定是针对一般的后端。

任何人都知道我可以从哪里开始?我应该关注什么样的联接以及如何对最近的条目进行排序?

2 个答案:

答案 0 :(得分: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的最新报道是1月3日,而不是1月2日。)

加入Postgres是隐含的“内在联盟”。如果您的标签没有条目,则需要将连接更改为左连接。

答案 1 :(得分:0)

SQL Fiddle

您的示例数据与文字不符。表格入口标记应为

(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