【问题标题】:Making PostgreSQL respect the order of the inputted parameters?让PostgreSQL尊重输入参数的顺序?
【发布时间】:2010-02-12 23:44:13
【问题描述】:

这个问题有点历史——Is there a way to make a query respect the order of the inputted parameters?

我不熟悉构建“专门”查询,因此我假设如果我提供 IN 子句作为 SELECT 查询的一部分,它将以相同的顺序返回结果。不幸的是,事实并非如此。

SELECT * FROM artists WHERE id IN (8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37)
>>> [7, 32, 3, 8, 4, 2, 31, 9, 37, 13, 16, 1, 5, 15, 14]

(不包括我使用 Python 循环遍历结果并将 ID 附加到列表的步骤。)

所以问题是,有没有办法让 Postgres 尊重在 IN 子句中给出的参数的顺序,通过返回结果 same 顺序?

【问题讨论】:

    标签: python postgresql


    【解决方案1】:

    除非您指定ORDER BY 子句,否则查询结果将以不确定的顺序返回。

    如果您真的想以您请求的方式进行查询,那么您可以构造这样一个子句。这是一个使用部分数据的示例。

    create table artists (
    id integer not null primary key,
    name char(1) not null);
    
    insert into artists
    values
        (8, 'a'),
        (1, 'b'), 
        (2, 'c'),
        (15, 'd'),
        (14, 'e'),
        (3,  'f'),
        (13, 'g');
    
    select *
    from artists
    where id in (8, 1, 2, 15, 14, 3, 13)
    order by
        id = 8 desc,
        id = 1 desc,
        id = 2 desc,
        id = 15 desc,
        id = 14 desc,
        id = 3 desc,
        id = 13 desc;
    

    基于此和您的其他问题,我认为您的模型或您尝试执行此操作的方式有问题。也许你应该发布一个更通用的问题,关于如何做你想做的事情。

    如果你有艺术家和排名表,你应该可以做这样的事情(或者通过你的 ORM 做类似的事情)。

    select
        a.*
    from
        artists a,
        rankings r
    where
        a.id = r.artist_id
    order by
        r.score desc;
    

    【讨论】:

    • 感谢您的回答。我确实遗漏了很多关于我的应用程序如何工作的内容。长话短说,排名不仅对应于艺术家,还可以对应于我们提供的任意数量的对象类型。也就是说,我正在使用 Django 的泛型来创建这些关系,这使得我在这里尝试做的事情变得有点困难。
    • 很遗憾 Postgres 无法保留订单。这也可以让我免于很多麻烦!我处于类似的情况,并且排序顺序每分钟更改几次,所以我在我的应用程序中进行排序以防止完全不必要的数据库写入。所以订购不是一种选择,
    【解决方案2】:

    我建议你让 PostGreSQL 以任意顺序返回集合(特别是因为很难从 Django 接口进行细粒度的 SQL 级控制),然后在 Python 中按照你希望的方式对其进行排序 em> -- theresultset.sort(key=yourlistofids.index) 应该没问题(当theresultset 是数据库生成的任意顺序列表,yourlistofids 是您要保留其顺序的列表时)。

    【讨论】:

    • 另一种情况,我希望我能同时接受这两个答案。 :) 非常感谢,我将亲自走这条路,但为了让人们从谷歌上找到这个问题,我将接受应付的回答。
    • FWIW,我建议不要使用此解决方案。数据库旨在进行排序,而应用程序语言则不是。它会比让数据库排序慢得多。
    • @Theory,Python 在排序(适合内存的数据)方面是 superb -- 它的timsort 算法非常出色,也引起了很多关注,例如在 Java 世界中。你说(Python)“不是”“设计用于排序”是荒谬的,而它是如此伟大
    【解决方案3】:

    另一种方式:

    SELECT * 
    FROM artists 
    WHERE id IN (8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37)
    ORDER BY POSITION(id::text in '(8, 1, 2, 15, 14, 3, 13, 31, 16, 5, 4, 7, 32, 9, 37)');
    

    【讨论】:

    • 位置函数确定一个字符串在另一个字符串中的位置。这将无法正常工作,因为并非所有 id 的位数都相同。假设您希望 id 14 成为第一个。您最终可能会以 id 1 为第一。或 id 4。
    猜你喜欢
    • 2011-01-15
    • 2021-06-07
    • 2018-10-12
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    相关资源
    最近更新 更多