每组最大的n组略有不同

问题描述 投票:2回答:2

我读过这个comment,它解释了greatest-n-per-group问题及其解决方案。不幸的是,我面临着一种略有不同的方法,我没有找到解决方案。

假设我有一个表格,其中包含有关用户的一些基本信息。由于实施,此信息可能重复也可能不重复:

+----+-------------------+----------------+---------------+
| id |     user_name     | user_name_hash |    address    |
+----+-------------------+----------------+---------------+
|  1 | peter_jhones      | 0xFF321345     | Some Av       |
|  2 | sally_whiterspoon | 0x98AB5454     | Certain St    |
|  3 | mark_jackobson    | 0x0102AB32     | Some Av       |
|  4 | mark_jackobson    | 0x0102AB32     | Particular St |
+----+-------------------+----------------+---------------+

正如你所看到的,mark_jackobson出现了两次,虽然每个外观的地址都不同。

每隔一段时间,一个ETL进程会查询新的user_names并获取每个user_name_hashs的最新记录。后来,它将user_name存储在一个表中,以表明它已经导入了某些+----------------+ | user_name_hash | +----------------+ | 0xFF321345 | | 0x98AB5454 | +----------------+

SELECT DISTINCT user_name_hash
FROM my_table
EXCEPT
SELECT user_name_hash
FROM my_hash_table

一切都以以下查询开头:

SELECT MAX(id)
FROM my_table
WHERE user_name_hash IN (
  SELECT DISTINCT user_name_hash
  FROM my_table
  EXCEPT
  SELECT user_name_hash
  FROM my_hash_table)
GROUP BY user_name_hash

这样,我就可以从我的表中选择新的哈希值。由于我需要查询最近出现的哈希,我将其包装为子查询:

id

完善!使用我的新用户的SELECT address, user_name_hash FROM my_table WHERE Id IN ( SELECT MAX(id) FROM my_table WHERE user_name_hash IN ( SELECT DISTINCT user_name_hash FROM my_table EXCEPT SELECT user_name_hash FROM my_hash_table) GROUP BY user_name_hash) s,我可以查询地址如下:

comment

从我的角度来看,上面的查询是有效的,但它似乎并不是最优的。读这个SELECT tb1.address, tb1.user_name_hash FROM my_table tb1 INNER JOIN my_table tb2 ON tb1.user_name_hash = tb2.user_name_hash LEFT JOIN my_hash_table ht ON tb1.user_name_hash = ht.user_name_hash AND tb1.id > tb2.id WHERE ht.user_name_hash IS NULL; ,我注意到我可以使用连接查询相同的数据。由于我没有写出所需的查询,任何人都可以帮助我并指出我的方向吗?

这是我尝试过的查询,没有成功。

SELECT
  address,
  user_name_hash
FROM my_table t1
JOIN (
  SELECT MAX(id) maxid
  FROM my_table t2
  WHERE NOT EXISTS (
    SELECT 1
    FROM my_hash_table t3
    WHERE t2.user_name_hash = t3.user_name_hash
  )
  GROUP BY user_name_hash
) t ON t1.ID = t.maxid

提前致谢。

编辑>我正在使用PostgreSQL

sql postgresql
2个回答
1
投票

我相信你正在寻找这样的东西:

NOT EXISTS

我使用EXCEPT而不是SELECT t1.address, t1.user_name_hash, MAX(id) AS maxid FROM my_table t1 LEFT JOIN my_hash_table th ON t1.user_name_hash = th.user_name_hash WHERE th.user_name_hash IS NULL GROUP BY t1.address, t1.user_name_hash HAVING MAX(id) = (SELECT MAX(id) FROM my_table t1) ,因为优化器更清楚。


0
投票

您可以使用左外连接获得更好的性能(以获取尚未导入的最新记录),然后计算这些记录的最大ID(HAVING子句中的子查询)。

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.