每组最大的n组略有不同

时间:2017-12-19 16:14:09

标签: sql postgresql

我已阅读此comment,其中解释了StartFromBeginning问题及其解决方案。不幸的是,我面临的方法略有不同,我找不到解决方案。

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

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 | +----+-------------------+----------------+---------------+ 出现两次,但每个外观的地址都不同。

每隔一段时间,一个ETL进程会查询新的mark_jackobson并获取每个进程的最新记录。然后,它会将user_name存储在一个表格中,以表明它已导入某个user_name_hash

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

从我的角度来看,上面的查询有效,但它似乎不是最佳的。阅读此comment,我注意到我可以使用连接查询相同的数据。由于我没有写出所需的查询,任何人都可以帮助我并指出我的方向吗?

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

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)

提前致谢。

编辑>我正在使用 PostgreSQL

2 个答案:

答案 0 :(得分:1)

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

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

我使用NOT EXISTS代替EXCEPT,因为优化程序更清楚。

答案 1 :(得分:0)

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

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)