生成行号而不排序任何列

时间:2018-05-31 06:21:06

标签: sql sql-server firebird

我想按照添加数据的相同顺序生成行号。 以下查询适用于SQL Server。

SELECT *,ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS SNO FROM TestTable

我需要标准查询才能在Firebird中实现相同的场景。任何人都可以建议我这个吗?

2 个答案:

答案 0 :(得分:0)

您不能将row_number() over (order by (select 100))与Firebird一起使用,因为Firebird - 根据SQL标准的要求 - 需要from的{​​{1}}子句。 Firebird中的等价物为select

最好的解决方案是使用row_number() over (order by (select 100 from rdb$database))的实际列来确保确定性顺序。

在查看SQL:2016标准时,order by不需要order by(但它适用于row_number()rank())。不幸的是,看起来微软也对dense_rank()应用了这个要求,可能是因为秩功能的一致性,也许是因为没有命令的row_number()没有多大意义。将row_number()与SQL Server一起使用会产生错误“函数'row_number'必须具有带ORDER BY的OVER子句。”,但与Firebird一起使用。

SQL Server还强制执行窗口函数中的order by不是数字列引用。将row_number() over ()与SQL Server一起使用会产生错误“窗口函数,聚合和NEXT VALUE FOR函数不支持整数索引作为ORDER BY子句表达式。”,但适用于Firebird(尽管{ {1}}被视为文字1,而不是列引用,与选择级别的row_number() over (order by 1)相反。

SQL Server也不支持在窗口函数中按顺序使用常量或文字。将1与SQL Server一起使用会产生错误“窗口函数,聚合和NEXT VALUE FOR函数不支持常量作为ORDER BY子句表达式。”,但适用于Firebird。

我确实找到了一个适用于Firebird 3和SQL Server 2017的技巧,但这是一个肮脏的黑客:

order by

这是有效的,因为SQL Server不将row_number() over (order by '1')视为常量,而是将其视为函数,这意味着它不属于“不允许常量”规则。

请注意,此技巧可能会产生不一致的行号(例如,使用不同常量计算的Firebird多窗口函数将产生不同的值,并且在选择级别row_number() over (order by current_user) 之前评估窗口函数),并且您可以想要考虑是否不应该只是在应用程序中跟踪行索引。

答案 1 :(得分:0)

一种方法可能是使用ORDER BY RAND()

CREATE TABLE TestTable(i INT);
INSERT INTO TestTable(i) VALUES (10);
INSERT INTO TestTable(i) VALUES (20);
INSERT INTO TestTable(i) VALUES (30);

SELECT TestTable.*,ROW_NUMBER() OVER (ORDER BY RAND()) AS SNO 
FROM TestTable;

db<>fiddle demo - Firebird

db<>fiddle demo - SQL Server