2016-10-27 4 views
0

다음 행에서 값을 가져 오는 SQL 방식을 찾고 있습니다. 같은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 

내가 100K있어 + 내 ETL 응용 프로그램은 SQL을 허용하지만 저장 프로 시저가 아니기 때문에 SQL을 사용해야합니다.

To_Qty를 만들 수 있도록 어떻게 값을 얻을 수 있습니까?

+1

은 SQL 서버 버전에 따라, 당신은'lead'를 사용할 수 있습니다. 테이블에는 고유 한 순서가 없으므로 '다음'의 의미를 정의해야합니다. – HoneyBadger

+0

어떤 SQL Server 버전을 사용하고 있습니까? – Lamak

+1

'lead()'함수 –

답변

0
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 
+2

다른 방법을 사용하지 않고 왜 방법으로 문제를 해결할 수 있는지 설명해 주시겠습니까? –

+0

이것은 완벽합니다! 그것은 고객과 제품 모두를 고려하여 매력처럼 작동합니다. 고맙습니다!!!!!!!! :) – RobB

1

SQL Server 2012 이상 버전을 실행하는 경우 LAG 및 LEAD 함수를 사용하여 현재 행과 함께 이전 또는 이후 행에 액세스 할 수 있습니다.

0

LEAD 및 FIRST_VALUE 분석 함수를 사용하여 언급 한 결과를 생성 할 수 있습니다. LEAD() 함수를 사용하여 고객 그룹에서 다음 값을 검색 할 수 있습니다. FIRST_VALUE()는 고객 그룹에서 첫 번째 값을 제공합니다.

예를 들어 말하십시오. CUST = 23 ... LEAD는 13을 반환하고 FIRST_VALUE는 1 ... TO_QTY = LEAD - FIRST_VALUE, 즉 13-1 = 12를 반환합니다. 비슷한 방식으로 아래에 언급 된 수식은 테이블의 모든 100,000 행을 계산합니다.

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; 
1
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 
0

같은 열을 사용하지만 임시 증가 필드가 추가 된 임시 테이블에 데이터를 삽입하십시오. 주문한 물건을 넣으십시오. 나는 cust, prod, from_qty로 추측하고 있습니다. 이제 temp 테이블에서 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) 

그리고 99999를 수행 할 또 다른 항목은 존재하지 않는 절입니다.

그런 다음 새 테이블이나 수정 된 테이블에 데이터를 다시 삽입하십시오.

0
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 
관련 문제