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

时间:2018-02-22 17:47:01

标签: sql-server partitioning ranking

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

我有一个包含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它消除了具有多条记录的群集中的第一行,这是我不想要的。我怎么解决这个问题?我想过一个小组,但我不知道如何应用这个。

非常感谢!

2 个答案:

答案 0 :(得分:1)

编辑:完全更新新要求。这将仅显示与其关联多年的master_id的记录,但是它将显示与该master_id关联的所有记录,即使它们在同一年(参见600 vs 700)。

SQLFiddle here

我们将在cte1中执行你的year_rank,这样我们就可以用cte2中的MAX()函数聚合它来过滤掉max大于你想放在那里的任何变量的位置。然后,我们查询cte1并加入cte2,仅显示与其关联多年的master_id的记录。

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

答案 1 :(得分:0)

我想要消除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

现在我可以将所有这些放入临时表中并删除那些没有显示'的记录。在备注栏中。

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

相关问题