【问题标题】:Substitute the Lag() function with another similiar option in Sybase用 Sybase 中的另一个类似选项替换 Lag() 函数
【发布时间】:2017-09-27 00:26:07
【问题描述】:

在 stackoverflow 中的一些用户的帮助下,我找到了以下查询。问题是这个查询在 SQL Server 中运行良好,但在 Sybase 中却不行,因为它不支持 LAG()。我一直在尝试让它工作,但没有成功。

查询非常复杂,但如果您能用类似的东西替换 LAG() 函数,我们将不胜感激。

SELECT created
    , bname
    , total_share
FROM (
    SELECT TT.created
        , TT.bname
        , TT.total_share
        , lag(TT.total_share) OVER (
            PARTITION BY TT.bname ORDER BY TT.created
            ) AS prev_share
    FROM (
        SELECT DISTINCT t.created AS created
            , t.NAME AS bname
            , t.total_share
        FROM (
            SELECT cast(fsp.created AS VARCHAR(19)) AS created
                , e.NAME
                , e.initials
                , fsp.modified
                , CASE 
                    WHEN cl.price_per_item = 0
                        THEN CAST('' AS DECIMAL(18, 2))
                    ELSE CAST((fsp.new_price / cl.price_per_item * 100) AS DECIMAL(18, 2))
                    END AS new_share
                , CASE 
                    WHEN cl.price_per_item = 0
                        THEN CAST('' AS DECIMAL(18, 2))
                    ELSE CAST((prev / cl.price_per_item * 100) AS DECIMAL(18, 2))
                    END AS old_share
                , fs.STATE
                , CASE 
                    WHEN fsp.prev_price IS NULL
                        THEN 0
                    ELSE fsp.prev_price
                    END AS prev
                , fsp.new_price AS nprice
                , (prev - nprice) AS diff
                , new_share - old_share AS diff_share
                , old_share + diff_share AS total_share
            FROM project_manager pm
            INNER JOIN dba.project p ON pm.project = p.id
            LEFT JOIN dba.contract c ON p.id = c.project
            LEFT JOIN dba.contract_line cl ON cl.contract = c.id
            LEFT JOIN dba.product pt ON cl.product = pt.id
            LEFT JOIN dba.specified_product sp ON sp.product = pt.id
            LEFT JOIN dba.frozen_sale fs ON fs.spec_product = sp.id
                AND fs.contract = c.id
                AND fs.line = cl.idx
            LEFT JOIN dba.frozen_sale_split fsp ON fsp.frozen_sale = fs.id
                AND fsp.employee = pm.consultant
            LEFT JOIN dba.employee e ON fsp.employee = e.person
            LEFT JOIN dba.person ps ON fsp.creator = ps.id
            WHERE p.id = 50000002735
                AND e.NAME IS NOT NULL
            ) AS t

        ) TT /* here */
    ) x
WHERE (
        prev_share IS NULL
        OR prev_share  total_share
        )
ORDER BY created
    , bname

【问题讨论】:

  • 您是否尝试过将 row_number 窗口函数应用于整个表,然后在适当滞后的行号上使用子查询连接?
  • 不,我没有,坦率地说,这对我来说相当先进。由于一些帮助,我得到了 Lag 函数。

标签: sql sybase


【解决方案1】:

以下代码未经测试,但方法是使用 row_number 窗口函数为每一行分配一个序号(代码中的rnum),按created 值排序。这是在初始 CTE 中完成的。然后,主查询将该 CTE 与自身连接起来,连接条件为 rnum 值中的差为 1。

 with inp as (
    SELECT TT.created
        , TT.bname
        , TT.total_share
        , row_number over(order by TT.created) as rnum
    FROM (
        SELECT DISTINCT t.created AS created
            , t.NAME AS bname
            , t.total_share
        FROM (
            SELECT cast(fsp.created AS VARCHAR(19)) AS created
                , e.NAME
                , e.initials
                , fsp.modified
                , CASE 
                    WHEN cl.price_per_item = 0
                        THEN CAST('' AS DECIMAL(18, 2))
                    ELSE CAST((fsp.new_price / cl.price_per_item * 100) AS DECIMAL(18, 2))
                    END AS new_share
                , CASE 
                    WHEN cl.price_per_item = 0
                        THEN CAST('' AS DECIMAL(18, 2))
                    ELSE CAST((prev / cl.price_per_item * 100) AS DECIMAL(18, 2))
                    END AS old_share
                , fs.STATE
                , CASE 
                    WHEN fsp.prev_price IS NULL
                        THEN 0
                    ELSE fsp.prev_price
                    END AS prev
                , fsp.new_price AS nprice
                , (prev - nprice) AS diff
                , new_share - old_share AS diff_share
                , old_share + diff_share AS total_share
            FROM project_manager pm
            INNER JOIN dba.project p ON pm.project = p.id
            LEFT JOIN dba.contract c ON p.id = c.project
            LEFT JOIN dba.contract_line cl ON cl.contract = c.id
            LEFT JOIN dba.product pt ON cl.product = pt.id
            LEFT JOIN dba.specified_product sp ON sp.product = pt.id
            LEFT JOIN dba.frozen_sale fs ON fs.spec_product = sp.id
                AND fs.contract = c.id
                AND fs.line = cl.idx
            LEFT JOIN dba.frozen_sale_split fsp ON fsp.frozen_sale = fs.id
                AND fsp.employee = pm.consultant
            LEFT JOIN dba.employee e ON fsp.employee = e.person
            LEFT JOIN dba.person ps ON fsp.creator = ps.id
            WHERE p.id = 50000002735
                AND e.NAME IS NOT NULL
            ) AS t
        ) TT
    ) 
SELECT
    created
    , bname
    , total_share
    , prev.total_share as prev_share
FROM
    inp
    left join inp as prev on prev.rnum=inp.rnum-1
        and prev.bname=inp.bname
WHERE (
    prev.total_share IS NULL
    OR prev.total_share  total_share
    )
ORDER BY 
    created
    , bname

【讨论】:

  • 非常感谢您的帮助
猜你喜欢
  • 2021-10-29
  • 1970-01-01
  • 2010-12-15
  • 2023-03-13
  • 1970-01-01
  • 2017-12-25
  • 2021-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多