查询以计算特定列值的出现

时间:2017-11-10 07:20:33

标签: sql postgresql

假设我有一个包含以下值的表

1
1
1
2
2
2
3
3
3
1
1
1
2
2
2

我需要得到一个像这样的出局,它计算每个出现的时间 特别值

 1  1
 1  2
 1  3
 2  1
 2  2
 2  3
 3  1
 3  2 
 3  3
 1  1
 1  2
 1  3
 2  1
 2  2
 2  3

注意:这是一个示例表实际表是一个包含大量行和列的复杂表,查询包含更多条件

3 个答案:

答案 0 :(得分:2)

如果数字在不同的“岛屿”上重复,那么您需要计算一个值以便首先维护这些岛屿(grpnum)。可以通过从分区行号中减去原始的从上到下的行号(raw_rownum)来执行第一步。该结果为每个“岛”提供了该岛独有的参考,然后可用于对随后的行号进行分区。由于每个订单都会影响结果,我发现有必要使用单独的步骤并通过先前的计算,以便可以重复使用。

SQL Fiddle

MS SQL Server 2014架构设置

CREATE TABLE Table1  ([num] int);

INSERT INTO Table1  ([num])
VALUES  (1),(1),(1),(2),(2),(2),(3),(3),(3),(1),(1),(1),(2),(2),(2);

查询1

select
    num
    , row_number() over(partition by (grpnum + num) order by raw_rownum) rn
    , grpnum + num island_num
from (
    select
           num
         , raw_rownum - row_number() over(partition by num order by raw_rownum) grpnum
         , raw_rownum
    from (
          select
              num
             , row_number() over(order by (select null)) as raw_rownum
          from table1
         ) r
     ) d
;

<强> Results

| num | rn | island_num |
|-----|----|------------|
|   1 |  1 |          1 |
|   1 |  2 |          1 |
|   1 |  3 |          1 |
|   2 |  1 |          5 |
|   2 |  2 |          5 |
|   2 |  3 |          5 |
|   1 |  1 |          7 |
|   1 |  2 |          7 |
|   1 |  3 |          7 |
|   3 |  1 |          9 |
|   3 |  2 |          9 |
|   3 |  3 |          9 |
|   2 |  1 |         11 |
|   2 |  2 |         11 |
|   2 |  3 |         11 |

答案 1 :(得分:1)

SQL Server提供row_number()功能:

select ID, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ID) RN FROM <TABLE_NAME>

编辑:

select * , case when (row_number() over (order by (select 1))) %3 = 0 then 3 else
           (row_number() over (order by (select 1))) %3 end [rn] from table

答案 2 :(得分:0)

我认为您的样本存在问题,因为您有隐含的订单但不是明确的订单。无法保证数据库会按照列出的方式保存和存储值,因此必须有一些固有的/显式的排序机制来告诉数据库将这些值完全按照您列出的方式返回。

例如,如果您这样做:

update test
set val = val + 2
where val < 3

您会发现select *不再以您预期的方式回归。

你表示你的实际桌子很大,所以我假设你有这样的东西你可以使用。表格中应该有一些东西可以表明你想要的顺序......也许是一个时间戳,或者也许是一个代理键。

那就是说,假设你有类似的东西可以利用它,我相信一系列的窗口函数都可以工作。

with rowed as (
  select
    val,
    case
      when lag (val, 1, -1) over (order by 1) = val then 0
      else 1
    end as idx,
    row_number() over (order by 1) as rn  -- fix this once you have your order
  from
    test
),
partitioned as (
  select
    val, rn,
    sum (idx) over (order by rn) as instance
  from rowed
)
select
  val, instance, count (1) over (partition by instance order by rn)
from
  partitioned

此示例按照它们在数据库中列出的方式排序,但您可能希望更改row_number函数以适应您的实际排序机制。

1   1   1
1   1   2
1   1   3
2   2   1
2   2   2
2   2   3
3   3   1
3   3   2
3   3   3
1   4   1
1   4   2
1   4   3
2   5   1
2   5   2
2   5   3