繁体   English   中英

SQL从下一行获取值

[英]SQL get value from next row

我正在寻找一种SQL方法来从下一行获取值。

我的数据如下所示:

CUST    PROD     From_Qty    Disc_Pct
23      Brush    1           0
23      Brush    13          1
23      Brush    52          4
77      Paint    1           0
77      Paint    22          7

我需要结束的是这个,(我想创建To_Qty行):

CUST    PROD     From_Qty    To_Qty    Disc_Pct
23      Brush    1           12        0
23      Brush    13          51        1              #13 is 12+1
23      Brush    52          99999     4              #52 is 51+1
77      Paint    1           21        0              #1  is 99999+1
77      Paint    22          99999     7              #22 is 21+1

我要执行10万以上的行,并且必须是SQL,因为我的ETL应用程序允许使用SQL,但不允许使用存储过程等。

如何从下一行获取值,以便创建To_Qty?

SELECT  *,
        LEAD([From_Qty], 1, 100000) OVER (PARTITION BY [CUST] ORDER BY [From_Qty]) - 1 AS To_Qty
FROM    myTable

LEAD()将根据[From_Qty]的顺序为您提供下一个值。.当[Cust]更改值时,您可以使用PARTITION BY [CUST]进行重置

或者您可以使用CTE和Row_Number。

WITH cte AS 
(
    SELECT  *,
            ROW_NUMBER() OVER (PARTITION BY [CUST] ORDER BY [From_Qty]) Rn
    FROM    myTable
)
SELECT  t1.*,
        ISNULL(t2.From_Qty - 1, 99999) To_Qty
FROM    cte t1
        LEFT JOIN cte t2 ON t1.Cust = t2.Cust AND t1.Rn + 1 = t2.Rn

如果您运行的是SQL Server 2012或更高版本,则可以使用LAG和LEAD函数访问前一行或后一行以及当前行。

您可以使用LEAD和FIRST_VALUE分析函数来生成您提到的结果。 通过使用LEAD()函数,可以检索客户组中的下一个值,而FIRST_VALUE()将给出客户组中的第一个值。

说例如。 CUST = 23 ... LEAD将返回13,而FIRST_VALUE将返回1 ... TO_QTY = LEAD-FIRST_VALUE即。 13-1 = 12。 以类似的方式,下面提到的公式将为表中的所有100k行计算。

    SELECT CUST,
           PROD,
           FROM_QTY,
           CASE WHEN LEAD( FROM_QTY,1 ) OVER ( PARTITION BY CUST ORDER BY FROM_QTY ) IS NOT NULL 
                THEN
           LEAD( FROM_QTY,1 ) OVER ( PARTITION BY CUST ORDER BY FROM_QTY ) -
 FIRST_VALUE( FROM_QTY ) OVER ( PARTITION BY CUST ORDER BY FROM_QTY )
                ELSE 99999
            END AS TO_QTY,
           DISC_PCT   
      FROM Yourtable;

将数据插入具有相同列的临时表中,但添加一个id自动增量字段。 按顺序插入它们,我假设是客户,产品,然后是from_qty。 现在,您可以在临时表上运行更新语句。

UPDATE #mytable
SET To_Qty = (SELECT From_Qty - 1 FROM #mytable AS next WHERE next.indexfield = #mytable.indexfield + 1 AND next.cust = #mytable.cust and next.prod = #mytable.prod)

然后另一个使用不存在子句执行99999。

然后将数据插入回到新表或修改后的表中。

declare  @Table table(CUST int, PROD varchar(50), From_Qty int, Disc_Pct int)
insert into @Table values
(23, 'Brush',    1,      0)
,(23, 'Brush',    13,     1)
,(23, 'Brush',    52,     4)
,(77, 'Paint',    1,      0)
,(77, 'Paint',    22,     7)

SELECT  CUST, Prod, From_qty, 
        LEAD(From_Qty,1,100000) OVER(PARTITION BY cust ORDER BY from_qty)-1 AS To_Qty,
        Disc_Pct
  FROM @Table
SELECT
 CUST, 
PROD, 
FROM_QTY , 
COALESCE(MIN(FROM_QTY) OVER (PARTITION BY CUST, PROD  ORDER BY FROM_QTY DESC ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) , 10000)-1, 
DISC_PCT
 FROM <tablename>
 ORDER BY CUST, PROD, FROM_QTY 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM