【问题标题】:Get the count of a value for each row in SQL获取 SQL 中每一行的值的计数
【发布时间】:2015-03-29 11:45:33
【问题描述】:

我有一个 SQL 问题。以下是我的数据和查询

select ID from table

ID

4   
4   
5   
3   
5   
3   
3

我应该将什么查询添加到我的选择列表中,以便它为每个特定行提供一个值(我不想要总计数,我想要类似出现排名的东西)。

4 1--this is the first time we got a 4 in the list, so 1
4 2--this is the second time we got a 4 in the list, so 2
5 1--this is the first time we got a 5 in the list, so 1
3 1--this is the first time we got a 3 in the list, so 1
5 2--this is the second time we got a 5 in the list, so 2
3 2--this is the second time we got a 3 in the list, so 2
3 3--this is the third time we got a 3 in the list, so 3

【问题讨论】:

  • 可能类似于[模式计算][1] [1]:stackoverflow.com/questions/11223003/…
  • 这是针对 MySQL 的,我认为这里没有任何帮助。 :(史蒂夫已经搞定了。
  • 没那么简单。 row_number() 是正确的方向,但要匹配预期的输出,诀窍是保留原始行顺序。

标签: sql-server


【解决方案1】:

要根据行的顺序生成编号,请使用row_number()rank()。问题是,row_number()does not guarantee the original order will be preserved。你可以试试这个:

select
    [id],
    row_number() over (partition by id, order by (select 1)) as [rank]
from @t

但是,你会发现结果不是原来的顺序,有些混乱:

id  rank
3   1
3   2
3   3
4   1
4   2
5   1
5   2

要保留原始行顺序,您可以使用identity 列构建临时表或表变量。从那里选择一个由id 分区的row_number()

declare @t table ([tkey] int identity(1,1) primary key clustered, [id] int)
insert into @t (id) values (4), (4), (5), (3), (5), (3), (3)

select
    [id],
    row_number() over (partition by [Id] order by [tkey]) as [rank]
from @t
order by [tkey]

请注意,最后的order by [tkey] 确实是必要的。该查询具有所需的结果:

id  rank
4   1
4   2
5   1
3   1
5   2
3   2
3   3

这是一种通用表表达式 (CTE) 方法。 CTE 添加row_number() 以保持原始顺序中的行。 (这相当于前面示例中的identity 列。)当它执行partition by id 时,实际排名来自第二个row_number()。这会导致第 1 个 4 得到 1,第 2 个 4 得到 2,依此类推。

第二个row_number() 必须按原始顺序排序才能正确排名,但这仍然不足以保留输出中的顺序。最后的order by 确保结束顺序相同。

declare @t table (id int)
insert into @t (id) values (4), (4), (5), (3), (5), (3), (3)

;with [tRows] (rownum, id) as
(
    select
        row_number() over (order by (select 1)) as [rownum],
        [id]
    from @t
)
select
    [id],
    row_number() over (partition by id order by [rownum]) as [rank]
from [tRows]
order by [rownum]

这个查询也有想要的结果:

id  rank
4   1
4   2
5   1
3   1
5   2
3   2
3   3

在本例中,您可以使用rank() 代替第二个row_number()this question 很好地解释了函数之间的区别。如果不知何故,第一个 row_number() 生成了重复的行号,rank() 将无法正常工作,但这不会发生。

【讨论】:

  • 非常感谢保罗。我尝试了 row_number() 和 rank() 但我搞砸了 order by。所以,我无法得到结果。
【解决方案2】:

你想要 ROW_NUMBER():

SELECT 
    [Id],
    ROW_NUMBER() OVER (PARTITION BY [Id] ORDER BY [Id])
FROM ...

您可能需要更改 Order By 子句以获得正确的输出。

【讨论】:

  • row_number() over (partition by id order by id) 本身不会保留原始行顺序。如果这很重要,您将不得不以某种方式生成订单。请注意,row_number() over (partition by id order by (select 1)) 也会丢失原始排序。 (我正在测试 SQL Server 2014 与 2012 的兼容性。)
  • 这就是为什么我提到需要更改 Order By 子句的原因。我猜表中还有其他字段可以用来设置顺序。
  • 非常感谢保罗和史蒂夫。我尝试了 row_number() 和 rank() 但我搞砸了 order by。所以,我无法得到结果。这两个答案都对我有用。
猜你喜欢
  • 1970-01-01
  • 2021-10-04
  • 2021-04-25
  • 1970-01-01
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多