代码之家  ›  专栏  ›  技术社区  ›  andynormancx

带行计数器的SQLServer SQL查询

  •  25
  • andynormancx  · 技术社区  · 16 年前

    我有一个SQL查询,它返回一组行:

    SELECT id, name FROM users where group = 2
    

    我还需要包括一个具有递增整数值的列,因此第一行需要在计数器列中有1,第二行有2,第三行有3,以此类推

    这里显示的查询只是一个简化的示例,实际上查询可以是任意复杂的,有几个连接和嵌套查询。

    我知道这可以通过使用一个带有自动编号字段的临时表来实现,但有没有一种方法可以在查询本身中实现呢?

    4 回复  |  直到 16 年前
        1
  •  31
  •   LukeH    16 年前

    对于初学者来说,大致如下:

    SELECT my_first_column, my_second_column,
        ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter
    FROM my_table
    

    然而,值得注意的是 ROW_NUMBER() OVER (ORDER BY ...) 构造仅决定以下值 Row_Counter ,它不能保证结果的顺序。

    除非 SELECT 它本身有一个明确的 ORDER BY 子句中,结果可以按任何顺序返回,具体取决于SQL Server决定如何优化查询。 ( See this article for more info .)

    保证结果的唯一方法是 总是 被退回 行_计数器 顺序是对两者应用完全相同的顺序 选择 以及 ROW_NUMBER() :

    SELECT my_first_column, my_second_column,
        ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter
    FROM my_table
    ORDER BY my_order_column  -- exact copy of the ordering used for Row_Counter
    

    上述模式将始终以正确的顺序返回结果,并且适用于简单的查询,但对于可能包含数十个表达式的“任意复杂”查询呢 订购方式 条款?在这种情况下,我更喜欢这样的东西:

    SELECT t.*
    FROM
    (
        SELECT my_first_column, my_second_column,
            ROW_NUMBER() OVER (ORDER BY ...) AS Row_Counter  -- complex ordering
        FROM my_table
    ) AS t
    ORDER BY t.Row_Counter
    

    使用嵌套查询意味着不需要复制复杂的 订购方式 子句,这意味着更少的混乱和更容易的维护。外部 ORDER BY t.Row_Counter 也使您的其他开发人员更清楚地了解查询的意图。

        2
  •  10
  •   Cade Roux    16 年前

    在SQL Server 2005及更高版本中,您可以使用 ROW_NUMBER() 函数,它具有排序顺序和计数(和重置)所针对的组的选项。

        3
  •  3
  •   miken32 Amit D    8 年前

    最简单的方法是使用可变行计数器。然而,这将是两个实际的SQL命令。一是设置变量,然后查询如下:

    SET @n=0;
    SELECT @n:=@n+1, a.* FROM tablename a
    

    您的查询可以像您喜欢的那样复杂,包括连接等。我通常将其设置为存储过程。您可以使用该变量获得各种乐趣,甚至可以使用它来计算字段值。关键是 :=

        4
  •  -3
  •   Ross Presser    9 年前

    这里有一种不同的方法。 如果你有几个不可连接的数据表,或者你出于某种原因不想同时计算所有行,但你仍然希望它们是同一行计数的一部分,你可以创建一个为你完成这项工作的表。

    例子:

    create table #test (
            rowcounter int identity,
            invoicenumber varchar(30)
            )
    
    insert into #test(invoicenumber) select [column] from [Table1]
    
    insert into #test(invoicenumber) select [column] from [Table2]
    
    insert into #test(invoicenumber) select [column] from [Table3]
    
    select * from #test
    
    drop table #test