在子查询中使用LIMIT简化查询,在子查询和外部查询中重复使用WHERE子句

时间:2018-09-02 12:34:26

标签: sql postgresql postgresql-9.6

SQL Fiddle

假设有以下表格:

customers

+----+------------------------+------------+------------+
| 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 |
+----+------------------------+------------+------------+

transactions

+----+-----------+-------------+------+
| 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;

results

+----------+-------------+------------------------+------------+------------+------+
| 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查询获得相同结果的其他方法?

1 个答案:

答案 0 :(得分:2)

您可以使用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