【问题标题】:Alternative to SQL window functions in SybaseSybase 中 SQL 窗口函数的替代方案
【发布时间】:2020-01-09 15:54:39
【问题描述】:

我正在使用 Sybase Adaptive Server Enterprise(版本 12.5.0.3)。尝试使用Row_number() OVER (Partition by columnname order by columnname)。当我执行查询时,它会抛出一个异常,指出 OVER 附近的语法不正确。我已经为 sybase 数据库搜索了正确的 row_number() 语法,但语法没有任何问题。我猜正在使用的 Sybase 版本不支持row_number() OVER。我什至尝试过dense_rank() OVER,但遇到了同样的错误。

我想知道这是真的语法问题还是因为Sybase的低版本不支持关键字?

如果问题出在版本上,那么对于 sybase 数据库,row_number OVER 和 dense_rank() OVER 是否有任何替代方案。

我的查询:

select  cr.firstname, cr.lastname, cr.dob,cr.phone,
          row_number() over (patition by cr.dob order by createddate) "rank"       
          from ff.CrossReferenceTable cr

错误信息:

Server Message:  Number  156, Severity  15
               Server 'MyServer', Line 1:
               Incorrect syntax near the keyword 'over'.

【问题讨论】:

  • SQL Advantage 目前是版本 11,我认为 SQL Anywhere 没有版本 12.5.1,因此您可能正在使用 Sybase ASE 或 Sybase IQ。您能否说明您使用的是什么 DBMS?
  • 我已经执行了下面的查询并找到了输出。 Select @@version 输出为 "Adaptive Server Enterprise/12.5.0.3/EBF 10690 IR/P/RS6000/AIX 4.3.3/rel12503/1915/32-bit/FBO/Thu Jan 23 12:19:08 2003"
  • Sybase ASE 12.5 不支持row_numberover。这是使用临时表的人建议的row_number 的解决方法。 stackoverflow.com/questions/16608469/…
  • 另外,这里是文档链接:infocenter.sybase.com/help/index.jsp?topic=/… 您可能会找到Transact SQL 用户指南参考手册:构建块参考手册:命令有助于确定支持哪些命令。
  • 谢谢迈克尔。此信息很有帮助。

标签: sybase sap-ase window-functions


【解决方案1】:

好吧,不幸的是 Sybase ASE 不支持row_number() 函数以及rank()dense_rank()。 但是,在一些简单的情况下,如果不使用分区子句,则可以像这样进行转换

select rank=identity(music), * into #new_temp_tab1 from CrossReferenceTable order by createddate
select firstname, lastname, dob, phone, rank from #new_temp_tab1

在您的情况下,它会有点复杂,我可以建议使用带有临时表的游标来模拟row_number() 的行为分区。 请看下面的例子:

create table CrossReferenceTable
(
    firstname varchar(50),
    lastname varchar(50), 
    dob int,
    phone char(10), 
    createddate date
)
go

create proc sp_CrossReferenceTable
as
begin
    declare @i int
    declare @cur_firstname varchar(50)
    declare @cur_lastname varchar(50)
    declare @cur_dob int
    declare @cur_phone varchar(10)
    declare @cur_rank int

    declare cur cursor for 
        select 
                cr.firstname, 
                cr.lastname, 
                cr.dob,
                cr.phone, 
                count(*) AS "rank" 
            from 
                CrossReferenceTable cr
            group by 
                cr.dob 
            order by
                cr.dob, 
                createddate

    CREATE TABLE #CrossReferenceTable_TEMP 
    (
        firstname varchar(50),
        lastname varchar(50), 
        dob int,
        phone char(10),
        rank INT
    )

    open cur
    fetch cur into 
        @cur_firstname, 
        @cur_lastname, 
        @cur_dob, 
        @cur_phone, 
        @cur_rank

    set @i = @cur_rank

    while @@SQLSTATUS = 0 
    begin
        if @i = 0
            set @i = @cur_rank

        insert into #CrossReferenceTable_TEMP 
        select 
            @cur_firstname, 
            @cur_lastname, 
            @cur_dob,
            @cur_phone, 
            case 
                when @cur_rank > 1 then @cur_rank - (@i - 1) 
                ELSE @cur_rank
            end as "rank"

        set @i = @i - 1

        fetch cur into 
            @cur_firstname,
            @cur_lastname, 
            @cur_dob, 
            @cur_phone, 
            @cur_rank
    end

    select 
            firstname, 
            lastname, 
            dob, 
            phone, 
            rank 
        from 
            #CrossReferenceTable_TEMP
end
go

exec sp_CrossReferenceTable

【讨论】:

  • 这个答案已被标记为“不是答案”,我怀疑是因为没有任何格式它是多么的混乱。我尝试修复格式,但我对这种语言不是很熟悉(我认为它是 SQL?我通常不会在 SQL 中编写超过 3 行的内容,所以我不知道格式化更长的约定代码。)我怀疑大代码块中可能应该有一些缩进。除了格式之外,这对我来说似乎是一个很好的答案。
  • @ArtOfWarfare 感谢您的格式化!你做的绝对正确。我希望答案是有用的。
【解决方案2】:

尝试下面的通用查询与ROW_NUMBER()具有相同的效果

SELECT 
  A.MyPartitionColumn, 
  A.MyRunningNumberColumn, 
  ( SELECT count(*) 
    FROM MyTable 
    WHERE    MyPartitionColumn      = A.MyPartitionColumn
         AND MyRunningNumberColumn <= A.MyRunningNumberColumn
  ) AS "Row_Number"
FROM      MyTable  A
ORDER BY  MyPartitionColumn, MyRunningNumberColumn

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2019-11-09
    • 2012-09-26
    相关资源
    最近更新 更多