在窗口函数 postgresql 中选择条件

Posted

技术标签:

【中文标题】在窗口函数 postgresql 中选择条件【英文标题】:Selecting on a condition in window function postgresql 【发布时间】:2019-07-17 07:36:22 【问题描述】:

我正在使用 postgresql 并应用窗口函数。以前我必须找到具有相同姓氏和地址(街道地址和城市)的第一个 gid,所以我只需将姓氏放在窗口函数中的 partition by 子句中。

但现在我需要找到第一个姓氏不同的 g_id。虽然地址相同,但我该怎么做?

这是我以前做的。

SELECT g_id as g_id,
 First_value(g_id) 
 OVER (PARTITION BY lname,street_address , city , 
           order by  last_date DESC NULLS LAST )as c_id,
street_address as street_address  FROM my table;

让我们说这是我的数据库


g_id | l_name | street_address | city | last_date
_________________________________________________
x1   | bar    | abc road       | khi  | 11-6-19

x2   | bar    | abc road       | khi  | 12-6-19

x3   | foo    | abc road       | khi  | 19-6-19

x4   | harry  | abc road       | khi  | 17-6-19

x5   | bar    | xyz road       | khi  | 11-6-19

_________________________________________________

在之前的场景中: 因为如果我为第一行运行我的 c_id,它应该返回“x2”,因为它考虑了这些行:

_________________________________________________
g_id | l_name | street_address | city | last_date
_________________________________________________
x1   | bar    | abc road       | khi  | 11-6-19

x2   | bar    | abc road       | khi  | 12-6-19
_________________________________________________

并返回最新的 last_date 行。

我现在想要选择这些行(具有相同 street_address 和 city 但没有相同 l_name 的行):


g_id | l_name | street_address | city | last_date
_________________________________________________
x1   | bar    | abc road       | khi  | 11-6-19

x3   | foo    | abc road       | khi  | 19-6-19

x4   | harry  | abc road       | khi  | 17-6-19
_________________________________________________

输出将是 x3。

我想以某种方式比较 last_name 列,如果它不等于 last name 的当前值,然后按地址字段进行分区。如果没有行满足条件 c_id 应该等于当前 g_id

【问题讨论】:

请添加一些示例数据和预期输出 11-6-19 最新到12-6-19 怎么样?你是说最早的吗? 请注意我在 last_day 订购时使用了 DESC,我想要最近日期的大多数行。 “raod”是错字吗?如果你想取另一个街道名称,一个更不同的名字会很有用......我仍然不确定你的意思是“姓氏不一样”......你的样本对于强调这个恕我直言并不是很有用 是的 raod 是一个错字,让它可以是任何值。在窗口函数中,我想选择 l_name 与迭代器姓氏的当前值不同但相同 street_address 和 city 的行。 【参考方案1】:

查看您的预期输出,不清楚您是否希望每个组最早或最旧。您可以在使用DISTINCT ON的查询中为last_date相应地更改ORDER BY

SELECT DISTINCT ON ( street_address, city, l_name) * 
   FROM   mytable 
ORDER  BY street_address, 
          city, 
          l_name, 
          last_date  --change this to last_date desc if you want latest

DEMO

【讨论】:

这如何包括我只想考虑 last_name 不等于当前行的 last_name 的行的部分。 @AQEELALTAF : l_nameDISTINCT ON 的一部分 因为在第一个条件下,答案是完全正确的,所以必须点赞! @S-Man:谢谢!我们在 SO 中发现很少有事先有足够信息的问题,除非有严重要求。【参考方案2】:

在此chat讨论细节后:

demo:db<>fiddle

SELECT DISTINCT ON (t1.g_id) 
    t1.*,
    COALESCE(t2.g_id, t1.g_id) AS g_id
FROM
    mytable t1
    LEFT JOIN mytable t2
    ON t1.street_address = t2.street_address AND t1.l_name != t2.l_name
ORDER BY t1.g_id, t2.last_date DESC

【讨论】:

【参考方案3】:

这是我使用子查询解决它的方法 创建示例表。

CREATE TABLE mytable
("g_id" varchar(2), "l_name" varchar(5), "street_address" varchar(8), "city" varchar(3), "last_date" date)

;

INSERT INTO mytable
("g_id", "l_name", "street_address", "city", "last_date")
VALUES
('x1', 'bar', 'abc road', 'khi', '11-6-19'),
('x2', 'bar', 'abc road', 'khi', '12-6-19'),
('x3', 'foo', 'abc road', 'khi', '19-6-19'),
('x4', 'harry', 'abc road', 'khi', '17-6-19'),
('x5', 'bar', 'xyz road', 'khi', '11-6-19')

;

查询获取 g_ids

SELECT * ,
(select b.g_id from mytable b where (base.g_id = b.g_id) or (base.l_name <> 
b.l_name and base.street_address = b.street_address and base.city = b.city ) 
order by b.last_date desc  limit 1)
from mytable base

【讨论】:

以上是关于在窗口函数 postgresql 中选择条件的主要内容,如果未能解决你的问题,请参考以下文章

连续 ID 块上的 PostgresQL 窗口函数

如何在 Postgresql 的窗口函数中“区分”计数?

在 PostgreSQL 中优化窗口函数以使用索引

在 django ORM 中使用 postgresql 窗口函数的干净方法?

Postgresql - 窗口函数聚合

PostgreSQL:使用窗口函数返回单行