分区和选择具有多个记录的集群

partitioning and selecting clusters with multiple records

问题的 header 可能令人困惑,所以我把我的问题写成文字:

我有一个 table,带有 master_ids、ID 和年份。 master_id 可以包含不同的 ID。每个 Id 都与一年相关联。我已经按 master_id 划分并给每年一个排名 (year_rank)。

+-----------+----+------+-----------+
| master_id | id | year | year_rank |
+-----------+----+------+-----------+
| 100       | 1  | 2017 | 1         |
| 100       | 2  | 2016 | 2         |
| 100       | 3  | 2015 | 3         |
| 200       | 9  | 2001 | 1         |
| 300       | 5  | 2020 | 1         |
| 300       | 4  | 2010 | 2         |
| 400       | 7  | 1999 | 1         |
| 400       | 11 | 1996 | 2         |
| 500       | 20 | 1999 | 1         |
| 600       | 25 | 2005 | 1         |
| 600       | 29 | 2005 | 1         |
+-----------+----+------+-----------+

我的目标是只选择记录多于 1 的集群来进行比较:

+-----------+----+------+-----------+
| master_id | id | year | year_rank |
+-----------+----+------+-----------+
| 100       | 1  | 2017 | 1         |
| 100       | 2  | 2016 | 2         |
| 100       | 3  | 2015 | 3         |
| 300       | 5  | 2020 | 1         |
| 300       | 4  | 2010 | 2         |
| 400       | 7  | 1999 | 1         |
| 400       | 11 | 1996 | 2         |
+-----------+----+------+-----------+

如果我将 year_rank > 1 放在何处,它会消除具有多个我不想要的记录的簇中的第一行。我该如何解决这个问题?我想到了一个分组依据,但我不知道如何应用它。

非常感谢!

编辑:针对新要求进行了全面更新。这将只显示 master_ids 的记录,这些记录与它们关联了多年,但是它会显示与 master_id 关联的所有记录,即使它们在同一年(参见 600 与 700)。

SQLFiddle here

我们将在 cte1 中执行您的 year_rank,以便我们可以将其与 cte2 中的 MAX() 函数聚合,以过滤掉 max 大于您想要放置在那里的任何变量的地方。然后我们查询 cte1 并加入 cte2 以仅显示 master_ids 的记录,这些记录与它们关联了多年。

WITH cte1 AS (
    SELECT
        master_id,
        id,
        year,
        RANK() OVER (PARTITION BY master_id ORDER BY year DESC) AS year_rank
    FROM tbl
    ),
cte2 AS (
    SELECT
        master_id
    FROM cte1
    GROUP BY master_id
    HAVING MAX(year_rank) > 1
    )

SELECT
    cte1.master_id,
    cte1.id,
    cte1.year,
    cte1.year_rank
FROM cte1
JOIN cte2 ON
    cte1.master_id = cte2.master_id

我想办法消除在 master_id:

中没有年份差异的行
select *,
case
  when (master_id = (lead(master_id) over (order by master_id))) and 
  (year = (lead(service_year) over (order by master_id))) then 'no show'

  when (master_id = (lag(master_id) over (order by master_id))) and 
  (year = (lag(service_year) over (order by master_id))) then 'no show'
  else ''
end as note
from table

现在我可以将所有这些放入临时 table 并删除注释列中具有 'no show' 的记录。

你怎么看这个?有没有更简单的方法?