使用Sybase中的另一个类似选项替换Lag()函数

时间:2017-09-26 14:11:38

标签: sql sybase

在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

1 个答案:

答案 0 :(得分:0)

以下代码未经测试,但方法是使用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