【问题标题】:Esqueleto/raw SQL -- Sorting a query by the result of a sort on another table?Esqueleto/raw SQL -- 根据对另一个表的排序结果对查询进行排序?
【发布时间】:2013-08-09 12:56:08
【问题描述】:

我实际上对 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 排在第二位,Boat 排在第三位:

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

通过我的研究,我发现我需要某种连接组合来执行此操作。但是到目前为止,我只找到了一对多关系的解决方案(通过他们最近的帖子在一个线程中排序主题),我想我理解它们,但没有一个涉及多对多的这些三向连接关系。

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

有人知道我可以从哪里开始吗?我应该查看哪种联接以及如何对最近的条目进行排序?

【问题讨论】:

    标签: sql haskell yesod esqueleto


    【解决方案1】:

    另一种解决方案:

    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 中的联接是隐含的“内部联接”。如果您可能有没有条目的标签,您需要将连接更改为左连接。

    【讨论】:

    • 如果不需要标签ID(问题中不清楚),它可以工作。
    • 更新为包含标签 ID。我同意问题中所需的输出不是很清楚。 @justin,请澄清这是否不是您需要的输出。
    • 输出就足够了,我只需要一种方法来引用某种形状或形式的行。我只是不确定如何排序。谢谢:)
    【解决方案2】:

    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
    

    【讨论】:

    • 感谢您的更正和解决方案 :) 我很抱歉,我选择最佳答案有点武断,因为这两种解决方案似乎都有效,但我仍然无法让它在我的 ORM 中工作所以我的最终解决方案是两者兼而有之。
    猜你喜欢
    • 2012-10-10
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    • 2015-04-27
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多