表有重复数据,无法让两个聚合函数在 SQL Query 中工作

Posted

技术标签:

【中文标题】表有重复数据,无法让两个聚合函数在 SQL Query 中工作【英文标题】:Table has duplicate data and can't get two aggregates functions to work in SQL Query 【发布时间】:2016-03-06 02:56:39 【问题描述】:

问题在于“地址”表有多个条目,其中用户更新了他们的地址。我只需要最新的。我尝试在“地址”表中使用MAX(uPDATED_AT),但出现错误。好吧,我首先编写了下面的代码,并意识到很多行是重复的或接近重复的。我只需要将他们的 last 更改为他们的地址,但在尝试将另一个聚合添加到 HAVING 子句时出现错误。有人可以帮忙吗?我是 SQL 的新手,但很想知道这个问题并在以后纠正它。

顺便说一下,我正在使用 PostgreSQL

Select
  last_name,
  first_name,
  donator,
  customer_id,
  phone, 
  address,
  city,
  state,
  zipcode,
  events.buyer_id

  from events 

  join addresses on events.buyer_id = addresses.buyer_id 
  inner join customer_extras on addresses.buyer_id = customer_extras.buyer_id
  inner join Customer_roles on events.buyer_id = Customer_roles.buyer_id
  inner join People on Customer_roles.buyer_id = People.id

  group by 
  customer_id,
  member_status,
  events.event_type,
  first_name,
  last_name,
  address,
  city,
  state,
  phone,
  donator,
  zipcode,
  events.buyer_id

  HAVING MIN(events.created_at) between '2015-06-01'
  and '2015-08-01' and event_type ILIKE 'MEMBER_TABLET%' and member_status IN 
  ('moved','never answered', 'refused', 'complete')

【问题讨论】:

使用dense_rank函数 我会在哪里使用它?并感谢您的评论! 【参考方案1】:

您需要使用窗口函数,您的查询将如下所示

select t.*, dense_rank() over (partition by <column_with_duplicate_values> order by <date> desc) dr from ...

以上查询按降序排列。您需要包含在另一个查询中

select * from (<above_query>) q where dr=1;

【讨论】:

我似乎无法让您的排名代码正常工作。你能帮忙吗?我需要知道我的查询适合在哪里或如何。在您的代码此处部分中运行我的代码时出现错误。请,非常感谢您的帮助。我把工作带回家,因为我真的很想尽快完成这项工作。 这是经过测试的查询并为您修改。 “select * from (select * from (select t.*, row_number() over (partition by userid order by date desc) dr from address t) q where q.dr = 1) q1 join ...;”您需要通过在join子句后添加表来进行修改 关于您的回复,我有几个问题。我是 sql 新手,不熟悉 t.* 。这是什么意思?我知道。但不是。 t 是 from 子句中查询的别名 "select t.*, dense_rank() over (partition by order by desc) dr from t;跨度>
【参考方案2】:

假设您的addresses 表有一个名为create_date 的字段(我猜,但您可以使用您的实际字段名称),我想您想使用我最喜欢的分析函数row_number:

with most_recent_address as (
  select a.*, row_number() over (partition by buyer_id order by create_date desc) as rn
  from addresses as a  -- fix is here
)
Select 
  last_name, first_name, donator, customer_id,
  phone, address, city, state, zipcode,
  events.buyer_id
from events 
  join most_recent_address a on events.buyer_id = a.buyer_id and a.rn = 1
  inner join customer_extras on addresses.buyer_id = customer_extras.buyer_id
  inner join Customer_roles on events.buyer_id = Customer_roles.buyer_id
  inner join People on Customer_roles.buyer_id = People.id
where
  event_type ILIKE 'MEMBER_TABLET%' and 
  member_status IN ('moved','never answered', 'refused', 'complete')
group by 
  customer_id, member_status, events.event_type,
  first_name, last_name, address, city,
  state, phone, donator, zipcode, events.buyer_id
HAVING
  MIN(events.created_at) between '2015-06-01' and '2015-08-01'

同样,如果排名机制不是 create_date,则将其更改为应有的值。

根据您的数据大小,您可能需要切换到max 分析。它不会调用order by,因此应该是 O(n)。但是,请注意,如果您有两个相同的 create_date 值用于相同的 buy_id,这将产生两条记录而不是一条。您比我更了解您的数据,因此您可能可以评估这种风险与改进的性能:

with most_recent_address as (
  select a.*, max(create_date) over (partition by buyer_id) as max_date
  from addresses as a
)
Select 
  last_name, first_name, donator, customer_id,
  phone, address, city, state, zipcode,
  events.buyer_id
from events 
  join most_recent_address a on events.buyer_id = a.buyer_id and a.create_date = a.max_date
  inner join customer_extras on addresses.buyer_id = customer_extras.buyer_id
  inner join Customer_roles on events.buyer_id = Customer_roles.buyer_id
  inner join People on Customer_roles.buyer_id = People.id
where
  event_type ILIKE 'MEMBER_TABLET%' and 
  member_status IN ('moved','never answered', 'refused', 'complete')
group by 
  customer_id, member_status, events.event_type,
  first_name, last_name, address, city,
  state, phone, donator, zipcode, events.buyer_id
HAVING
  MIN(events.created_at) between '2015-06-01' and '2015-08-01'

另外,你没有问这个,但你可能注意到我把你的两个条件从having 移到了where 子句。这应该有助于提高查询性能,因为您要在分组之前而不是之后消除行。仅当您将条件应用于分组函数时,Having 才是必需的(超过 where)。由于排序/分组是数据库上最昂贵的操作之一,这对于大型数据集可能会产生很大的影响。

【讨论】:

如果它不起作用,请为您的表发布 DDL。你的努力听起来可行。 在您的设备上出现此错误?错误:缺少表“a”的 FROM 子句条目第 2 行:选择 a.*, row_number() over (partition by person_id orde... 好的,我会发布一些 ddl。我只是看到 a.* 给了麻烦。我不确定 a.* 实际上是什么意思。我看到 a.* 很多,但我从来没有使用过它。和*一样吗​​?我想这不是只是想知道。 我的错...我忘记将“地址”别名为 a。现在修复它。 Address People Events Customer_Roles Customer_Extras Buyer_id pk First_Name string created_at datetime donator string home_phone string Address1 string Last_Name string event_type string Customer_id string Buyer_id 唯一 id Address2 string Buyer_id 唯一 id Buyer_id 唯一 id Buyer_id 唯一 id 城市字符串 州字符串 邮政编码字符串 Updated_At 日期时间

以上是关于表有重复数据,无法让两个聚合函数在 SQL Query 中工作的主要内容,如果未能解决你的问题,请参考以下文章

SQL滑动窗口聚合(不使用窗口函数)

聚合函数和GROUP BY的问题

SQL:从 2 列数据源创建聚合表

在sql中使用聚合函数进行SELECT [重复]

让 SQL 查询更快更好

查询没有重复和聚合函数或 GROUP BY 子句问题。 - 重复