Sql 查询以检查列值是否多次出现
我有一个PostgreSQL查询:Sql 查询以检查列值是否多次出现,sql,postgresql,Sql,Postgresql,我有一个PostgreSQL查询: SELECT DISTINCT ON ("contract"."contract_id") "contract"."id" FROM "contract_versions" "contract" WHERE "contract"."client_id" = 1 GROUP BY "contract"."contract_id", "contract"."id" ORDER BY "contract"."contract_id", "contract"."c
SELECT DISTINCT ON ("contract"."contract_id") "contract"."id"
FROM "contract_versions" "contract"
WHERE "contract"."client_id" = 1
GROUP BY "contract"."contract_id", "contract"."id"
ORDER BY "contract"."contract_id", "contract"."change_effective_date" DESC
我想添加一些东西,比如如果合同id出现不止一次,那么更改生效日期>=现在
数据集:
id | contract_id | client_id | change_effective_date
-----+-------------+-----------+-----------------------
100 | 10 | 1 | 2020-05-17 00:00:00
200 | 10 | 1 | 2020-05-16 00:00:00
300 | 10 | 1 | 2020-05-14 00:00:00
400 | 20 | 1 | 2020-05-17 00:00:00
500 | 30 | 1 | 2020-05-13 00:00:00
600 | 30 | 1 | 2020-05-14 00:00:00
预期结果:
id | contract_id | client_id | change_effective_date
-----+-------------+-----------+-----------------------
200 | 10 | 1 | 2020-05-16 00:00:00
400 | 20 | 1 | 2020-05-17 00:00:00
600 | 30 | 1 | 2020-05-14 00:00:00
如果合同id的计数大于1,我希望更改生效日期小于或等于今天的行
我尝试使用:
SELECT DISTINCT ON ("contract"."contract_id") "contract"."id",
COUNT("contract"."contract_id") AS cnt
FROM "contract_versions" "contract"
WHERE "contract"."client_id" = 1 AND
CASE WHEN "cnt" > 1 THEN "contract"."change_effective_date" <= now() END
GROUP BY "contract"."contract_id", "contract"."id"
ORDER BY "contract"."contract_id", "contract"."change_effective_date" DESC
但其抛出的错误列cnt不存在
谢谢您的查询中有两个问题: 在第一个查询中,您有: 错误:列contract.change\u effective\u date必须出现在 GROUP BY子句或在聚合函数中使用 在第二种情况下,您不能在查询中直接引用列别名cnt:您可以在另一个查询中这样做,该查询必须将原始查询作为派生表或内联视图引用。 以下是一个可能的解决方案:
select * from contract_versions;
id | contract_id | client_id | change_effective_date
-----+-------------+-----------+-----------------------
100 | 10 | 1 | 2020-05-14 14:00:00
100 | 10 | 1 | 2020-05-14 14:00:00
100 | 10 | 1 | 2020-05-14 14:00:00
100 | 20 | 1 | 2020-05-16 09:00:00
(4 rows)
Null display is "NULL".
SELECT DISTINCT ON (contract_id) contract_id,
change_effective_date
FROM contract_versions contract
WHERE client_id = 1
GROUP BY contract_id, id, change_effective_date
ORDER BY contract_id, change_effective_date DESC;
contract_id | change_effective_date
-------------+-----------------------
10 | 2020-05-14 14:00:00
20 | 2020-05-16 09:00:00
(2 rows)
SELECT DISTINCT ON (contract_id) contract_id,
COUNT(contract_id) AS cnt,
change_effective_date
FROM contract_versions contract
WHERE client_id = 1
GROUP BY contract_id, id, change_effective_date
ORDER BY contract_id, change_effective_date DESC;
contract_id | cnt | change_effective_date
-------------+-----+-----------------------
10 | 3 | 2020-05-14 14:00:00
20 | 1 | 2020-05-16 09:00:00
(2 rows)
SELECT
contract_id,
CASE WHEN cnt > 1 THEN change_effective_date <= now()
END
FROM
(
SELECT DISTINCT ON (contract_id) contract_id,
COUNT(contract_id) AS cnt,
change_effective_date
FROM contract_versions contract
WHERE client_id = 1
GROUP BY contract_id, id, change_effective_date
ORDER BY contract_id, change_effective_date DESC
) v;
contract_id | case
-------------+------
10 | t
20 | NULL
(2 rows)
我从来没有看到过“清晰”与“分组”相结合。可以先聚合,然后从聚合结果中选取行,但这不是您正在做的,也不是您想要的。您希望ORDER by子句为DISTINCT ON应用的排名考虑当前日期
SELECT DISTINCT ON (contract_id) *
FROM contract_versions
WHERE client_id = 1
ORDER BY
contract_id,
CASE WHEN change_effective_date <= CURRENT_DATE THEN 1 ELSE 2 END,
change_effective_date DESC;
演示:带行数窗口功能:
select t.id, t.contract_id, t.client_id, t.change_effective_date
from (
select *,
row_number() over (
partition by contract_id
order by (change_effective_date > now())::int, change_effective_date desc
) rn
from contract_versions
) t
where t.rn = 1
order by t.id
您的问题中不清楚,因为如果合同id的值只属于一个客户id,则示例数据只包含一个客户id。
如果不是这样,则必须在上述查询中进行更改:
partition by contract_id
致:
看。
结果:
在合同id为10的变更生效日期中输入不同的日期。它并没有给出最新的行,而只是选择找到的第一行。我想检索具有最新更改生效日期但合同id不同的行,如果某些合同id出现在更改生效日期之前不止一次,请编辑您的问题以添加一些输入数据和预期的查询结果。谢谢,这很有效。请您解释一下这一行:如果更改生效日期到今天,我们会先订购,因为我们给他们排序键1,而其他人会给他们排序键2。因此,我们在2020-05-17之前得到2020-05-16,例如,如果合同id在今天和将来都有行。毕竟,排序顺序只是DISTINCT ON选择其行的排序顺序。@ThorstenKettner。DISTINCT ON也可以用于GROUP BY。考虑一个查询,在这里你想得到像每个城市中最有秩序的东西。”Gordon Linoff:我同意。我只是以前没有见过使用它,但这可能是因为主要使用Oracle。如果PostgreSQL是我的DBMS,我很肯定我自己也会使用它:-谢谢你给我举个例子。这一个也有用,谢谢,但它更复杂。
partition by contract_id, client_id
| id | contract_id | client_id | change_effective_date |
| --- | ----------- | --------- | ------------------------ |
| 200 | 10 | 1 | 2020-05-16 00:00:00.000 |
| 400 | 20 | 1 | 2020-05-17 00:00:00.000 |
| 600 | 30 | 1 | 2020-05-14 00:00:00.000 |