Mag*_*o C 4 postgresql order-by
我在 Postgres 9.3 数据库中有这个表:
我需要使用列的内容order,并limit进行排序和筛选此表。该表将按列排序first_name。
最终结果将如下图所示:
注意:对不起,如果这对你来说很简单,但我无法解决这个问题。所有邮件地址均由 www.mockaroo.com 生成。如果您的地址在此列表中,请不要怪我。
order和limit列将始终具有相同的数据。order可能是asc或desc也limit可能是任何整数值(但所有行都将是相同的值。它来自分组查询。
虽然您的解决方案很聪明,但它对性能不利,因为必须为每一行单独计算要排序的值。更重要的是,您的查询不能使用普通索引。
我建议将技巧移至LIMIT子句并使用UNION ALL. 通过这种方式,查询总体上变得更便宜,并且可以使用索引(这会破坏不能使用的竞争对手)。
WITH l AS (
SELECT CASE WHEN ordr = 'a' THEN lim ELSE 0 END AS lim_a
, CASE WHEN ordr = 'd' THEN lim ELSE 0 END AS lim_d
FROM test
LIMIT 1
)
(SELECT * FROM test ORDER BY first_name LIMIT (SELECT lim_a FROM l))
UNION ALL
(SELECT * FROM test ORDER BY first_name DESC LIMIT (SELECT lim_d FROM l));
Run Code Online (Sandbox Code Playgroud)
两者之一SELECT得到LIMIT 0并且永远不会被执行。您会在EXPLAIN ANALYZE输出中看到“从未执行过” 。
在 Postgres 9.4 的快速测试(50k 中的 35 行)中,没有索引的速度大约是两倍,但有索引的速度快了几个数量级。显然,差异随着表的大小而增加。
不要使用保留关键字作为标识符(正如您已经发现的那样):limandordr而不是and limit。order
不要用多余的值来膨胀你的表。如果你不能避免存储lim和ordr每一行,至少让它变小。基本布局:
CREATE TABLE test (
id int
, lim int
, ordr "char" CHECK (ordr IN ('a', 'd'))
, first_name text
, email text
);
Run Code Online (Sandbox Code Playgroud)
"char"作为一个简单的枚举类型是完美的,并且只占用 1 个字节。
创建索引:
CREATE INDEX test_first_name_idx ON test(first_name);
Run Code Online (Sandbox Code Playgroud)
细节:
| 归档时间: |
|
| 查看次数: |
3116 次 |
| 最近记录: |