SQL从下一行获取值

SQL从下一行获取值,sql,sql-server,tsql,Sql,Sql Server,Tsql,我正在寻找一种从下一行获取值的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行): 我有

我正在寻找一种从下一行获取值的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行):

我有超过100K行要执行此操作,必须是SQL,因为我的ETL应用程序允许SQL,但不允许存储过程等


如何从下一行获取值,以便创建到数量?

如果您运行的是SQL Server 2012或更高版本,则可以使用滞后和超前函数来访问当前行之前或之后的行。

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

比如说CUST=23。。。LEAD将返回13,FIRST_值将返回1。。。TO_数量=领先-第一个_值,即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;
LEAD()将根据
[来自数量]
的顺序为您获取下一个值。。当
[CUST]
更改值时,可以使用[CUST]分区来重置

或者您可以使用CTE和Row_编号

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

将数据插入具有相同列但添加了id自动增量字段的临时表中。插入订购的产品,我假设是客户、产品,然后是从数量。 现在可以在临时表上运行update语句

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)
然后另一个用not exists子句执行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
卡斯特, 戳 从数量, 合并(最小(起始数量)超过(按客户划分,按起始数量描述行划分,介于1个之前和1个之前之间),10000)-1, 光碟 从…起 按客户、产品、发件人数量订购
根据您的sql server版本,您可以使用
lead
。您确实需要定义“下一步”的含义,因为表没有固有的顺序。您使用的是什么版本的SQL Server?使用
lead()
函数值进入的逻辑是什么?您是否介意包括一个解释,说明您的方法为什么以及如何在不引入其他问题的情况下解决问题?这太完美了!它既考虑到客户又考虑到产品,而且工作起来很有魅力。谢谢你!!!!!!!:)
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)
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