具有特殊标准的组的相关性

问题描述 投票:0回答:1

我们需要获得列NEED的结果,需要按ORDER列的顺序按GROUP列进行相关分组,并且在FLAG列更改时会增加。

GROUP   ORDER   FLAG    NEED
1111    1       0       1
1111    2       0       1
1111    3       1       2
1111    4       1       2
1111    5       1       2
1111    6       1       2
1111    7       1       2
1111    8       0       3
1111    9       1       4
1111    10      1       4
1111    11      0       5
1111    12      0       5
1111    13      0       5
6666    1       0       1
6666    2       0       1
6666    3       1       2
6666    4       1       2

我们尝试下面的代码,但是我们需要更清洁的SQL Server 2008支持

if object_id('tempdb..#temp2','u') is not NULL
drop table #temp2
SELECT *
    ,ROW_NUMBER() OVER(oRDER BY (SELECT NULL)) RN
INTO #temp2
FROM DBO.PRUEBA​

SELECT T1.*
    ,SUM(CASE WHEN T1.NUM_GROUP = T2.NUM_GROUP and t1.NUM_FLAG = t2.NUM_FLAG THEN 0 ELSE 1 END) OVER (PARTITION BY T1.NUM_GROUP ORDER BY T1.rn)[Rank]
FROM #temp2 T1
LEFT JOIN #temp2 T2 ON T1.rn = T2.rn+1
order by t1.NUM_GROUP, t1.NUM_ORDER

我共享表和记录的创建

CREATE TABLE DBO.PRUEBA
(
    NUM_GROUP INT,
    NUM_ORDER INT,
    NUM_FLAG INT
)

INSERT INTO DBO.PRUEBA VALUES (1111, 1, 0)
INSERT INTO DBO.PRUEBA VALUES (1111, 2, 0)
INSERT INTO DBO.PRUEBA VALUES (1111, 3, 1)
INSERT INTO DBO.PRUEBA VALUES (1111, 4, 1)
INSERT INTO DBO.PRUEBA VALUES (1111, 5, 1)
INSERT INTO DBO.PRUEBA VALUES (1111, 6, 1)
INSERT INTO DBO.PRUEBA VALUES (1111, 7, 1)
INSERT INTO DBO.PRUEBA VALUES (1111, 8, 0)
INSERT INTO DBO.PRUEBA VALUES (1111, 9, 1)
INSERT INTO DBO.PRUEBA VALUES (1111, 10, 1)
INSERT INTO DBO.PRUEBA VALUES (1111, 11, 0)
INSERT INTO DBO.PRUEBA VALUES (1111, 12, 0)
INSERT INTO DBO.PRUEBA VALUES (1111, 13, 0)
INSERT INTO DBO.PRUEBA VALUES (6666, 1, 0)
INSERT INTO DBO.PRUEBA VALUES (6666, 2, 0)
INSERT INTO DBO.PRUEBA VALUES (6666, 3, 1)
INSERT INTO DBO.PRUEBA VALUES (6666, 4, 1)

SELECT * FROM DBO.PRUEBA
sql sql-server sql-server-2008 sql-server-2008-r2
1个回答
0
投票

一种可能的优化方法是首先创建临时表。

代替使用SELECT INTO

并且具有一个主键,该主键有益于用于获取以前的NUM_FLAG的自联接。

CREATE TABLE DBO.PRUEBA
(
    NUM_GROUP INT NOT NULL,
    NUM_ORDER INT NOT NULL,
    NUM_FLAG INT NOT NULL,
    PRIMARY KEY (NUM_GROUP, NUM_ORDER)
);
GO
INSERT INTO DBO.PRUEBA 
(NUM_GROUP, NUM_ORDER, NUM_FLAG)
VALUES
  (1111, 1, 0)
 ,(1111, 2, 0)
 ,(1111, 3, 1)
 ,(1111, 4, 1)
 ,(1111, 5, 1)
 ,(1111, 6, 1)
 ,(1111, 7, 1)
 ,(1111, 8, 0)
 ,(1111, 9, 1)
 ,(1111, 10, 1)
 ,(1111, 11, 0)
 ,(1111, 12, 0)
 ,(1111, 13, 0)
 ,(6666, 1, 0)
 ,(6666, 2, 0)
 ,(6666, 3, 1)
 ,(6666, 4, 1)
IF OBJECT_ID('tempdb..#tmpPRUEBA', 'U') IS NOT NULL
    DROP TABLE #tmpPRUEBA; 

CREATE TABLE #tmpPRUEBA
(
    NUM_GROUP INT NOT NULL,
    RN_GROUP INT NOT NULL,
    NUM_ORDER INT NOT NULL,
    NUM_FLAG INT NOT NULL,
    PRIMARY KEY (NUM_GROUP, RN_GROUP)
);
GO
INSERT INTO #tmpPRUEBA
(NUM_GROUP, NUM_ORDER, NUM_FLAG, RN_GROUP)
SELECT NUM_GROUP, NUM_ORDER, NUM_FLAG
, ROW_NUMBER() OVER (
      PARTITION BY NUM_GROUP 
      ORDER BY NUM_ORDER) AS RN_GROUP
FROM DBO.PRUEBA;
GO
SELECT 
t1.NUM_GROUP, 
t1.NUM_ORDER, 
t1.NUM_FLAG,
SUM(CASE 
    WHEN t1.NUM_FLAG = t2.NUM_FLAG 
    THEN 0 
    ELSE 1 
    END)
    OVER (PARTITION BY t1.NUM_GROUP 
          ORDER BY t1.RN_GROUP) AS [Rank]
FROM #tmpPRUEBA t1
LEFT JOIN #tmpPRUEBA t2
  ON t2.NUM_GROUP = t1.NUM_GROUP
 AND t2.RN_GROUP = t1.RN_GROUP - 1;
GO
NUM_GROUP | NUM_ORDER | NUM_FLAG |秩--------:| --------:| -------:| ---:1111 | 1 | 0 | 1个1111 | 2 | 0 | 1个1111 | 3 | 1 | 21111 | 4 | 1 | 21111 | 5 | 1 | 21111 | 6 | 1 | 21111 | 7 | 1 | 21111 | 8 | 0 | 31111 | 9 | 1 | 41111 | 10 | 1 | 41111 | 11 | 0 | 51111 | 12 | 0 | 51111 | 13 | 0 | 56666 | 1 | 0 | 1个6666 | 2 | 0 | 1个6666 | 3 | 1 | 26666 | 4 | 1 | 2

db <>小提琴here

© www.soinside.com 2019 - 2024. All rights reserved.