查询以检查列值是否出现多次

时间:2020-05-16 06:19:27

标签: 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"."change_effective_date" DESC

我想添加一些内容,例如如果contract_id出现多次,则change_effective_date> = now()

数据集:

 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

如果contract_id的计数大于1,我希望行的change_effective_date小于或等于今天

我尝试使用:

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

但抛出错误column "cnt" does not exist

谢谢

3 个答案:

答案 0 :(得分:0)

您的查询中有2个问题:

  1. 在第一个查询中,您有:

错误:列“ contract.change_effective_date”必须出现在 GROUP BY子句或在聚合函数中使用

  1. 在第二个查询中,您不能直接在查询中引用列别名(“ 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)

答案 1 :(得分:0)

我从未见过let timeString = "5:36" let timeStringArray = timeString.split(separator: ":") let minutesInt = Int(timeStringArray[0]) ?? 0 let secondsInt = Int(timeStringArray[1]) ?? 0 let resultInt = minutesInt * 60 + secondsInt print(resultInt) DISTINCT ON结合使用。可以(首先进行聚合,然后从该聚合结果中选择行),但这不是您要执行的操作,也不是您想要的。您希望GROUP BY的{​​{1}}子句应用的排名考虑当前日期。

ORDER BY

演示:https://dbfiddle.uk/?rdbms=postgres_12&fiddle=f709d18b23504dfaf9f586ace231be1d

答案 2 :(得分:0)

具有row_number()窗口功能:

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 

这个问题尚不清楚,因为如果client_id的值仅属于一个contract_id,则示例数据仅包含1个client_id
如果不是这种情况,则必须在上面的查询中进行更改:

partition by contract_id

收件人:

partition by contract_id, client_id

请参见demo
结果:

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