【问题标题】:Correlative by group with special criteria具有特殊标准的组相关性
【发布时间】:2020-04-05 05:20:17
【问题描述】:

我们需要得到 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

【问题讨论】:

  • 你说的cleaner是什么意思?查询是否为您提供了您想要的结果?
  • 查询代码在sql server 2008中不起作用,显示的代码看起来不是很干净。
  • 有什么不好的?你说的干净是什么意思?它看起来对我来说非常好。

标签: sql sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:

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

而不是使用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 | 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

db小提琴here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    相关资源
    最近更新 更多