【问题标题】:Sub queries and sorting? (ORDER BY)子查询和排序? (订购)
【发布时间】:2009-08-19 23:15:09
【问题描述】:

所以我的语法在所有三种情况下显然都是正确的(PostgreSQL 并没有抱怨任何事情),但是所有这三个查询的结果都以相同的顺序返回。当我从以下任何内容中添加/删除 DESC 时甚至更奇怪,它也没有任何影响。是否可以根据子查询的元素对结果进行排序?

Sort by affiliation
SELECT * FROM articles_view WHERE (1=1) 
AND spubid IN 
  (SELECT people.spubid FROM people WHERE (people.slast ilike 'doe') 
    GROUP BY people.spubid, people.slast, people.saffil) 
AND spubid IN 
  (SELECT status.spubid FROM status WHERE ((status.imonth >= 01 OR status.imonth IS NULL) AND status.iyear >= 2000) AND ((status.imonth <= 01 OR status.imonth IS NULL) AND status.iyear <= 2008) ORDER BY status.iyear, status.imonth)

Sort by last name, descending order
SELECT * FROM articles_view WHERE (1=1) 
AND spubid IN 
  (SELECT people.spubid FROM people WHERE (people.slast ilike 'doe') 
    GROUP BY people.spubid, people.slast, people.saffil ORDER BY people.slast DESC) 
AND spubid IN 
  (SELECT status.spubid FROM status WHERE ((status.imonth >= 01 OR status.imonth IS NULL) AND status.iyear >= 2000) AND ((status.imonth <= 01 OR status.imonth IS NULL) AND status.iyear <= 2008))

Sort by year/month descending order
SELECT * FROM articles_view WHERE (1=1) 
AND spubid IN 
  (SELECT people.spubid FROM people WHERE (people.slast ilike 'doe') 
    GROUP BY people.spubid, people.slast, people.saffil ) 
AND spubid IN 
  (SELECT status.spubid FROM status WHERE ((status.imonth >= 01 OR status.imonth IS NULL) AND status.iyear >= 2000) AND ((status.imonth <= 01 OR status.imonth IS NULL) AND status.iyear <= 2008) ORDER BY status.iyear, status.imonth DESC)

我只是不确定为什么 ORDER BY 条件对结果的顺序没有影响。

*********更新:

我最终做的是使用视图中的数组列(在本例中为articles_view)进行所有排序。这样我就可以在主查询中的“列”上做所有的事情,并且完全避免使用 JOINS。定义视图的方式是,与人员/状态表中的给定 pubid(主键)匹配的所有列(都具有 1->many)存储在视图中的数组列中。我的排序查询如下所示:

SELECT * FROM articles_view WHERE 
  ((articles_view.skeywords_auto ilike '%ice%') OR (articles_view.skeywords_manual ilike '%ice%')) 
  ORDER BY (articles_view.authors[1]).slast

这样做的原因是因为我总是知道数组的第一个成员(在 Postgres 中,第一个索引是 1 而不是通常的 0)是主要作者(或主要状态),这是我排序所需要的.

【问题讨论】:

    标签: sql postgresql sorting subquery sql-order-by


    【解决方案1】:

    所有子查询都在为条件提供一组结果以检查 spubid 的存在。您需要实际加入状态表,然后在外部查询的 order by 子句中使用列。

    类似:

    SELECT * 
    FROM articles_view
           INNER JOIN status ON articles_view.spubid = status.spubid
           INNER JOIN people ON articles_view.spubid = people.spubid
    WHERE ((status.imonth >= 01 OR status.imonth IS NULL) AND status.iyear >= 2000)
           AND ((status.imonth <= 01 OR status.imonth IS NULL)
           AND status.iyear <= 2008 AND people.slast ilike 'doe')
    ORDER BY status.iyear, status.imonth
    

    【讨论】:

    • 呃,这就是我害怕的,我真的很想避免使用连接(产品会变得太大,因此使用子查询代替)。
    • 使用内连接只会得到适当的结果,并且查询优化器应该确定一个计划,在应用连接之前去除不满足 where 子句的任何内容。
    【解决方案2】:

    您没有订购 outer 查询;您只订购 inner 查询。这是完全合法的,但是您对这些内部结果所做的只是将spubid 与它们进行比较,而您执行该操作的顺序并不重要。

    您要查找的是JOIN

    SELECT * 
    FROM articles_view
    INNER JOIN status ON (status.spubid = articles_view.spubid AND ((status.imonth >= 01 OR status.imonth IS NULL) AND status.iyear >= 2000) AND ((status.imonth <= 01 OR status.imonth IS NULL) AND status.iyear <= 2008))
    WHERE spubid IN 
      (SELECT people.spubid FROM people WHERE (people.slast ilike 'doe') 
       GROUP BY people.spubid, people.slast, people.saffil ) 
    ORDER BY status.iyear, status.imonth DESC
    

    (您也可以将另一个查找重写为连接,但为简单起见,我不理会那个。)

    【讨论】:

    • 由于我不提前知道用户是否想要对人员或状态表中的字段进行排序,因此我必须同时加入两者。问题是我剩下的产品,没有必要将那么多数据合并到查询中,但如果我想允许多种排序选项,这听起来是我唯一的选择。
    • 无论您是否JOIN,您都将这么多数据合并到查询处理中。如果您只关心返回那么多,那很容易更正:只需使用SELECT articles_view.* 而不是SELECT *
    【解决方案3】:

    您只是对 IN 语句使用的数据进行排序。您需要对顶级 Select 语句进行排序。

    编辑:

    由于 IN 子句中的 Select 语句不会对结果的整体排序做出贡献,因此您应该从中删除 order by 子句,从而防止服务器进行不必要的处理。

    【讨论】:

      【解决方案4】:

      我最终做的是使用视图中的数组列(在本例中为articles_view)进行所有排序。这样我就可以在主查询中的“列”上进行所有操作,并且完全避免使用 JOINS。定义视图的方式是,与人员/状态表中的给定 pubid(主键)匹配的所有列(都具有 1->many)存储在视图中的数组列中。我的排序查询如下所示:

      SELECT * FROM articles_view WHERE 
        ((articles_view.skeywords_auto ilike '%ice%') OR (articles_view.skeywords_manual ilike '%ice%')) 
        ORDER BY (articles_view.authors[1]).slast
      

      这样做的原因是因为我总是知道数组的第一个成员(在 Postgres 中,第一个索引是 1 而不是通常的 0)是主要作者(或主要状态),这是我排序所需要的.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-31
        • 2017-02-24
        • 2017-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多