【问题标题】:Add 'iteration number' column to SQL Select based on same values from two columns根据两列中的相同值将“迭代号”列添加到 SQL Select
【发布时间】:2021-02-01 10:47:41
【问题描述】:

我有一个 SQL (SQL Server) 语句 SELECT id, animalId, ownerId FROM myTable ORDER BY id,它输出以下数据:

id  | animalId | ownerId
------------------------
1   | 123      | 62
2   | 123      | 182
3   | 240      | 27
4   | 2        | 30
5   | 73       | 35
6   | 123      | 62
7   | 108      | 162
8   | 2        | 30
9   | 2        | 30
10  | 73       | 35

我想要做的是动态添加第四列,作为每行的计数器,这些行具有相同的 animalId 和 ownerId 值。所以结果输出是:

id  | animalId | ownerId | iterator
-----------------------------------
1   | 123      | 62      | 1           <-- First instance where animalId is 123 and ownerId is 62
2   | 123      | 182     | 1
3   | 240      | 27      | 1
4   | 2        | 30      | 1
5   | 73       | 35      | 1
6   | 123      | 62      | 2           <-- Second instance where animalId is 123 and ownerId is 62
7   | 108      | 162     | 1
8   | 2        | 30      | 2
9   | 2        | 30      | 3
10  | 73       | 35      | 2

谁能告诉我如何解决这个问题?

非常感谢。

【问题讨论】:

    标签: sql sql-server distinct-values


    【解决方案1】:

    您可以使用窗口函数 ROW_NUMBER():

    SELECT id, animalId, ownerId,
           ROW_NUMBER() OVER (PARTITION BY animalId, ownerId ORDER BY id) iterator 
    FROM myTable 
    ORDER BY id
    

    请参阅demo
    结果:

    > id | animalId | ownerId | iterator
    > -: | -------: | ------: | -------:
    >  1 |      123 |      62 |        1
    >  2 |      123 |     182 |        1
    >  3 |      240 |      27 |        1
    >  4 |        2 |      30 |        1
    >  5 |       73 |      35 |        1
    >  6 |      123 |      62 |        2
    >  7 |      108 |     162 |        1
    >  8 |        2 |      30 |        2
    >  9 |        2 |      30 |        3
    > 10 |       73 |      35 |        2
    

    【讨论】:

      【解决方案2】:

      如果您特别想计算 123/62 对的出现次数直到给定点(正如代码中的 cmets 所建议的那样),那么您可以使用累积和:

      select t.*,
             sum(case when ownerid = 62 and animalid = 123 then 1 else 0 end) over (order by id) as iterator
      from t;
      

      更合理的是,您希望所有配对都使用此功能。所以,使用row_number():

      select t.*,
             row_number() over (partition by ownerid, animalid order by id) as iterator
      from t;
      

      【讨论】:

        【解决方案3】:

        假设您想要按 ID 顺序排列的结果。 请在下面找到基于纯 ANSI SQL 语法的解决方案。

        创建表

        create table animalOwners( id int, animalId int , ownerId int );
        

        **插入数据**

        insert into animalOwners values (1,123,62);
        insert into animalOwners values(2,123,182);
        insert into animalOwners values(3,240,27);
        insert into animalOwners values(4,2,30);
        insert into animalOwners values(5,73,35);
        insert into animalOwners values(6,123,62);
        insert into animalOwners values(7,108,162);
        insert into animalOwners values(8,2,30);
        insert into animalOwners values(9,2,30);
        insert into animalOwners values(10,73,35);
        

        SQL 解决方案:

        select
            id,
            animalID,
            ownerId,
            (
            select
                count(*)
            from
                animalOwners innerTable
                where innerTable.id <= outerTable.id
                and innerTable.animalId = outerTable.animalId
                and innerTable.ownerId = outerTable.ownerId ) as counter
        from
            animalOwners outerTable
        order by
            id;
        

        如果你运行它,你会得到预期的输出。

        【讨论】:

          【解决方案4】:

          您正在寻找的术语是“窗口函数”。您可以对组中的成员进行排序(row_number over(按列排序),对组的成员进行计数(count(1) over(按列分区)),对它们进行排名、求和、平均等。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-04-14
            • 1970-01-01
            • 2019-03-25
            • 2020-09-24
            • 2021-11-29
            • 1970-01-01
            相关资源
            最近更新 更多