sql - 在子查询中使用 LIMIT 并在子查询和外部查询中重复 WHERE 子句来简化查询

标签 sql postgresql postgresql-9.6

SQL Fiddle

假设下表:

客户

+----+------------------------+------------+------------+
| id | company                | first_name | last_name  |
+----+------------------------+------------+------------+
|  1 | MDD                    | T          | H          |
|  2 | Aliance Magnet A LLP   | A          | Wilkinson  |
|  3 | MAF                    | C          | G          |
|  4 | QL                     | F          | B          |
|  5 | ARL                    | S          | P          |
|  6 | Q Corp.                | H          | H          |
|  7 | VQDA                   | L          | W          |
|  8 | AESC                   | E          | W          |
|  9 | Placement Incorporated | C          | Mendez     |
| 10 | Numpties United        | Y          | Cunningham |
+----+------------------------+------------+------------+

交易

+----+-----------+-------------+------+
| id | form_type | customer_id | due  |
+----+-----------+-------------+------+
|  1 | invoice   |           9 |    1 |
|  2 | payment   |           1 |    6 |
|  3 | invoice   |           7 |    9 |
|  4 | payment   |           9 |    4 |
|  5 | invoice   |           7 |    5 |
|  6 | payment   |           3 |    5 |
|  7 | invoice   |           9 |    5 |
|  8 | invoice   |           9 |   10 |
|  9 | invoice   |          10 |    1 |
| 10 | invoice   |           2 |    4 |
+----+-----------+-------------+------+

以下查询查找发票交易次数 > 0 的客户,但只返回与前三个客户相关的记录。

SELECT
  t.id AS trans_id,
  c.id AS customer_id,
  c.company,
  c.first_name,
  c.last_name,
  t.due
FROM (
  SELECT DISTINCT c.*
  FROM customers AS c
  INNER JOIN transactions AS t ON t.customer_id = c.id
  WHERE t.due > 0
  AND t.form_type = 'invoice'
  ORDER BY c.company, c.first_name, c.last_name
  LIMIT 3
) AS c
INNER JOIN transactions AS t ON t.customer_id = c.id
WHERE t.due > 0
AND t.form_type = 'invoice'
ORDER BY c.company, c.first_name, c.last_name;

结果

+----------+-------------+------------------------+------------+------------+------+
| trans_id | customer_id | company                | first_name | last_name  | due  |
+----------+-------------+------------------------+------------+------------+------+
|       10 |           2 | Aliance Magnet A LLP   | A          | Wilkinson  |    4 |
|        9 |          10 | Numpties United        | Y          | Cunningham |    1 |
|        1 |           9 | Placement Incorporated | C          | Mendez     |    1 |
|        7 |           9 | Placement Incorporated | C          | Mendez     |    5 |
|        8 |           9 | Placement Incorporated | C          | Mendez     |   10 |
+----------+-------------+------------------------+------------+------------+------+

有没有办法,例如使用窗口函数或公用表表达式,避免在内部和外部查询中重复 WHERE t.due > 0 AND t.form_type = 'invoice'ORDER BY 子句?还是通过其他方式通过单个 SQL 查询获得相同的结果?

最佳答案

您可以使用DENSE_RANK:

WITH cte AS (
  SELECT t.id AS trans_id,
         c.id AS customer_id,
         c.company,
         c.first_name,
         c.last_name,
         t.due,
         DENSE_RANK() OVER(ORDER BY c.company, c.first_name, c.last_name) rn
  FROM customers AS c
  JOIN transactions AS t ON t.customer_id = c.id
  WHERE t.due > 0 AND t.form_type = 'invoice'
)
SELECT * FROM cte WHERE rn <= 3;

DBFiddle Demo

关于sql - 在子查询中使用 LIMIT 并在子查询和外部查询中重复 WHERE 子句来简化查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52137081/

相关文章:

postgresql - Npgsql.PostgresException (0x80004005) : XX000: cache lookup failed for type 207852 when schema dropped

postgresql - array_agg with distinct 在 postgres 9.4 中有效但在 postgres 9.6 中无效

sql - 使用 TinyTds Ruby Gem 解析和运行 .sql 脚本

sql - 在 SQL 中是否可以有多个列级命名约束?语法是什么?

mysql - 按优先级排序的两列排序

PostgreSQL/JDBC 和 TIMESTAMP 与 TIMESTAMPTZ

postgresql - pg_dump 不设置 search_path

sql - 修改交叉连接查询

postgresql - 在 PL/pgSQL 中声明行类型变量

postgresql - 按多维数据集从 Group 中删除重复的 NULL