如何将自引用的复杂游标转换为更高效的 SQL 代码? CTE、交叉应用还是其他?

Posted

技术标签:

【中文标题】如何将自引用的复杂游标转换为更高效的 SQL 代码? CTE、交叉应用还是其他?【英文标题】:How to convert self-referencing complex Cursor to more efficient SQL code? CTE, CROSS-APPLY or something else? 【发布时间】:2017-03-14 15:24:54 【问题描述】:

我有以下简化的表结构。实际上 Slot 将是标识,并且该表是在几行之前新生成的,因此该列没有间隙。

Slot    SlotGroup   EventNum    ScheduleGroup
55      55          18          6
56      55          19          7
57      57          13          6
58      57          14          7
59      57          15          7
60      57          15          7
61      57          17          7
62      57          17          7
63      63          16          7
64      63          16          7
65      65          15          6
66      65          15          6

我需要遍历 MyTable 中的每条记录,并检查所有具有较小 Slot 的记录(在同一个 SlotGroup 内)是否具有相同的 ScheduleGroup 但不同的 EventNum:如果是这样,我应该在同一个 SlotGroup 中更新当前插槽之上的 Slot . 结果表应包含:

Slot    SlotGroup   EventNum    ScheduleGroup
...
59      59          15          7
60      59          15          7
61      61          17          7
62      61          17          7
...
63      63          16          7
64      63          16          7
...

由于在两个 SlotGroups 中都有前一行具有相同的 ScheduleGroup 但不同的 EventNum。

我在考虑 CTE 或 CROSS APPLY,但现在我不知道如何开始;您能帮我找到正确的解决方案吗?

目前我使用的代码是这样的,但 MyTable 中可能有数百行,我觉得这不是解决问题的最有效方法。

数据:

DECLARE @MyTable TABLE (
    Slot                        int --identity
  , SlotGroup                   int              NULL
  , EventNum                    int              NULL
  , ScheduleGroup               int
)

INSERT INTO @MyTable VALUES(55,55,18,6)
INSERT INTO @MyTable VALUES(56,55,19,7)
INSERT INTO @MyTable VALUES(57,57,13,6)
INSERT INTO @MyTable VALUES(58,57,14,7)
INSERT INTO @MyTable VALUES(59,57,15,7)
INSERT INTO @MyTable VALUES(60,57,15,7)
INSERT INTO @MyTable VALUES(61,61,14,6)
INSERT INTO @MyTable VALUES(62,61,15,7)
INSERT INTO @MyTable VALUES(63,61,16,7)
INSERT INTO @MyTable VALUES(64,61,16,7)
INSERT INTO @MyTable VALUES(65,65,15,6)
INSERT INTO @MyTable VALUES(66,65,15,6)

代码:

-- Go trhough each record in @MyTable and check if all records with a smaller Slot
--(within the same SlotGroup) have have the same ScheduleGroup but different EventNum.
--   If so do an update of the Slots above the current one (within the same SlotGroup)
DECLARE @nStartSlot         int--Will be set later within the loop
DECLARE @nCurScheduleGroup  int
DECLARE @nCurEventNum       int
DECLARE @nCurSlotGroup      int
DECLARE @nCurSlot           int
DECLARE mtCur CURSOR FOR
 SELECT ScheduleGroup, EventNum, SlotGroup, Slot FROM @MyTable

 OPEN mtCur
 FETCH NEXT FROM mtCur INTO @nCurScheduleGroup, @nCurEventNum, @nCurSlotGroup, @nCurSlot

 WHILE @@FETCH_STATUS = 0
 BEGIN
--Only the records with smaller Slot then the current one but within the same SlotGroup
--are interesting. therefore get the lowest Slot from the SAME SlotGroup. 
--(important if the current records is in a new SlotGroup based on the time splitting)
   IF NOT EXISTS (SELECT 1 
                  FROM   @MyTable mt
                  WHERE  mt.Slot = ISNULL(@nStartSlot, 0)
                  AND    mt.SlotGroup = @nCurSlotGroup
                 )
   BEGIN
     SELECT @nStartSlot = MIN(Slot) 
     FROM   @MyTable mt 
     WHERE  mt.SlotGroup = @nCurSlotGroup
   END

--Update all records above the current records but within the same SlotGroup,
--if we find a new EventNum (but ScheduleGroup) in the current SlotGroup.
   IF EXISTS (SELECT 1
              FROM   @MyTable mt
              WHERE  mt.Slot >= @nStartSlot
               AND   mt.Slot <= @nCurSlot
               AND   mt.ScheduleGroup = @nCurScheduleGroup
               AND   mt.EventNum != @nCurEventNum
             )
   BEGIN
     UPDATE mt
     SET    SlotGroup = @nCurSlot
     FROM   @MyTable mt
     WHERE  mt.Slot >= @nCurSlot
       AND  mt.SlotGroup = @nCurSlotGroup

     SELECT @nStartSlot = @nCurSlot
   END

   FETCH NEXT FROM mtCur INTO @nCurScheduleGroup, @nCurEventNum, @nCurSlotGroup, @nCurSlot
 END
 CLOSE mtCur
 DEALLOCATE mtCur

--编辑-- 应转换的其他数据集

来源 1

Slot    SlotGroup   EventNum    ScheduleGroup
16      13          3           778
17      17          10          778
18      17          10          778
19      17          9           778
20      17          9           778

结果 1

Slot    SlotGroup   EventNum    ScheduleGroup
...
19      19          9           778
20      19          9           778

来源 2

Slot    SlotGroup   EventNum    ScheduleGroup
39      39          10          778
40      39          10          778
41      39          9           778
42      39          10          778

结果 2

Slot    SlotGroup   EventNum    ScheduleGroup
39      39          10          778
40      39          10          778
41      41          9           778
42      42          10          778

--编辑 2-- 应转换的其他数据集

Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 8        8           1         978               8
 9        8           2         978               9
 10       8           2         977               9
 11       8           2         977               9
 12       8           1         977              12
 13       8           2         978              12
 14       8           1         978              14
 15       8           2         978              15
 16       8           1         978              16
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 17      17           1         331              17
 18      17           1         331              17
 19      17           1         331              17
 20      17           1         331              17
 21      17           1         331              17
 22      17           1         331              17
 23      17           1         331              17
 24      17           1         330              17
 25      17           1         330              17
 26      17           1         330              17
 27      17           1         330              17
 28      17           1         330              17
 29      17           1         330              17
 30      17           1         330              17
 31      17           2         330              31
 32      17           2         330              31
 33      17           2         330              31
 34      17           2         330              31
 35      17           2         330              31
 36      17           2         330              31
 37      17           2         330              31
 38      17           2         331              31
 39      17           2         331              31
 40      17           2         331              31
 41      17           2         331              31
 42      17           2         331              31
 43      17           2         331              31
 44      17           2         331              31
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 32      32           2         492              32
 33      32           6         492              33
 34      32           5         492              34
 35      32           6         492              35
 36      32           6         492              35
 37      32           6         492              35
 38      32           6         493              35
 39      32           6         492              35
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
219     219          18         065             219
220     219          16         065             220
221     219           1         246             220
222     219          16         065             220
223     219          18         065             223
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 39      39          10         113              39
 40      39           9         113              40
 41      39          10         112              40
 42      39           9         112              42
 43      39           1         241              42
 44      39           2         241              44
 45      39           2         241              44
 46      39           1         241              46
 47      39           1         241              46
 48      39           2         241              48
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 46      46          14         184              46
 47      46          14         183              46
 48      46          14         183              46
 49      46           1         184              49
 50      46          15         183              49
 51      46          15         183              49
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
148     148           6         725             148
149     148           5         725             149
150     148           5         725             149
151     148           6         725             151
152     148           6         723             151
153     148           6         724             151
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
150     150           2         221             150
151     150           1         221             151
152     150           2         221             152
153     150           2         221             152
154     150           1         222             152
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
122     122           3         462             122
123     122           2         462             123
124     122           2         463             123
125     122           2         463             123
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 36      36          10         617              36
 37      36           9         617              37
 38      36          10         618              37
 39      36           9         618              39
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 97      97          22         091              97
 98      97          22         091              97
 99      97          21         091              99
100      97          22         091             100
101      97          14         092             100
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
108     108          22         463             108
109     108          23         460             108
110     108          23         460             108
111     108          22         461             108
112     108          22         461             108
113     113          21         462             113
114     113          21         462             113
115     113          22         463             113
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
156     156          11         462             156
157     156          10         462             157
158     156          10         463             157
159     156          10         463             157
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 20      20           8         283              20
 21      21           7         283              21
 22      22           9         283              22
 23      23           8         283              23
 24      24          11         283              24
 25      25          10         283              25
 26      26          12         283              26
 27      26          11         283              27
 28      26           4         282              27
 29      26           4         282              27
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
105     105           2         418             105
106     106           1         418             106
107     106           1         418             106
108     108           2         418             108
109     106           1         418             109
110     106           1         418             109
111     108           2         418             111
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 57      57          13         776              57
 58      57          14         777              57
 59      57          15         777              59
 60      57          15         777              59
 61      61          14         776              61
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 9        9           3         771               9
 10       9           3         771               9
 11       9           3         771               9
 12       9           3         771               9
 13       9           1         772               9
 14       9           1         772               9
Slot    SlotGroup   EventNum    ScheduleGroup   ExpectedSlotGroup
 81      81          21         267              81
 82      81          22         267              82
 83      81          21         267              83
 84      81          21         267              83
 85      85          22         267              85
 86      85          22         267              85
 87      85          21         267              87

【问题讨论】:

在这里发布 ddl 和示例数据怎么样?否则没有人能真正提供帮助。 @SeanLange 不幸的是,这就是我所得到的,因为我正在尝试使一些旧的继承代码执行得更好 插槽组总是奇数有什么原因吗?或者当你更新时你会增加 2? @SqlZim 这只是完整数据的一个子集,我也出现过偶数,所以不要依赖这个:) @SqlZim SOURCE 1 我可以使用您的代码解决问题并将“或 NewSlotGroup != slotgroup”添加到最后一个 WHERE 条件 【参考方案1】:

使用lead()lag()

;with cte as (
select *
  , NewSlotGroup = min(slot) over (partition by testset, grp)
from (
  select *, grp = sum(sgrp) over (partition by testset order by slot)
  from (
    select *, sgrp = case 
      when lag(eventnum) over (partition by testset order by slot) = eventnum
        then 0
      when lag(eventnum) over (partition by testset, slotgroup order by slot) <> eventnum
       and lag(schedulegroup) over (partition by testset, slotgroup order by slot) <> schedulegroup
        then 0
      else 1
      end
    from t
    ) s
  ) g
)
update cte
  set SlotGroup  = NewSlotGroup
where SlotGroup != NewSlotGroup;

上述代码与您的新测试集之一冲突,(将光标移到此测试集上与我的结果匹配,而不是expectedslotgroup。请解释为什么预期的插槽组在类似情况下没有变化时会发生变化其他测试集:

rextester 演示:http://rextester.com/ZOH27910

+---------+------+-----------+----------+---------------+-------------------+----------+
| TestSet | slot | slotgroup | eventnum | schedulegroup | expectedslotgroup | conflict |
+---------+------+-----------+----------+---------------+-------------------+----------+
|       6 |   46 |        46 |       14 |           184 |                46 |          |
|       6 |   47 |        46 |       14 |           183 |                46 |          |
|       6 |   48 |        46 |       14 |           183 |                46 |          |
|       6 |   49 |        46 |        1 |           184 |                49 | X        |
|       6 |   50 |        46 |       15 |           183 |                49 | X        |
|       6 |   51 |        46 |       15 |           183 |                49 | X        |
+---------+------+-----------+----------+---------------+-------------------+----------+

完整结果:

+---------+------+-----------+----------+---------------+-------------------+----------+
| TestSet | slot | slotgroup | eventnum | schedulegroup | expectedslotgroup | conflict |
+---------+------+-----------+----------+---------------+-------------------+----------+
|       1 |    8 |         8 |        1 |           978 |                 8 |          |
|       1 |    9 |         9 |        2 |           978 |                 9 |          |
|       1 |   10 |         9 |        2 |           977 |                 9 |          |
|       1 |   11 |         9 |        2 |           977 |                 9 |          |
|       1 |   12 |        12 |        1 |           977 |                12 |          |
|       1 |   13 |        12 |        2 |           978 |                12 |          |
|       1 |   14 |        14 |        1 |           978 |                14 |          |
|       1 |   15 |        15 |        2 |           978 |                15 |          |
|       1 |   16 |        16 |        1 |           978 |                16 |          |
|       2 |   17 |        17 |        1 |           331 |                17 |          |
|       2 |   18 |        17 |        1 |           331 |                17 |          |
|       2 |   19 |        17 |        1 |           331 |                17 |          |
|       2 |   20 |        17 |        1 |           331 |                17 |          |
|       2 |   21 |        17 |        1 |           331 |                17 |          |
|       2 |   22 |        17 |        1 |           331 |                17 |          |
|       2 |   23 |        17 |        1 |           331 |                17 |          |
|       2 |   24 |        17 |        1 |           330 |                17 |          |
|       2 |   25 |        17 |        1 |           330 |                17 |          |
|       2 |   26 |        17 |        1 |           330 |                17 |          |
|       2 |   27 |        17 |        1 |           330 |                17 |          |
|       2 |   28 |        17 |        1 |           330 |                17 |          |
|       2 |   29 |        17 |        1 |           330 |                17 |          |
|       2 |   30 |        17 |        1 |           330 |                17 |          |
|       2 |   31 |        31 |        2 |           330 |                31 |          |
|       2 |   32 |        31 |        2 |           330 |                31 |          |
|       2 |   33 |        31 |        2 |           330 |                31 |          |
|       2 |   34 |        31 |        2 |           330 |                31 |          |
|       2 |   35 |        31 |        2 |           330 |                31 |          |
|       2 |   36 |        31 |        2 |           330 |                31 |          |
|       2 |   37 |        31 |        2 |           330 |                31 |          |
|       2 |   38 |        31 |        2 |           331 |                31 |          |
|       2 |   39 |        31 |        2 |           331 |                31 |          |
|       2 |   40 |        31 |        2 |           331 |                31 |          |
|       2 |   41 |        31 |        2 |           331 |                31 |          |
|       2 |   42 |        31 |        2 |           331 |                31 |          |
|       2 |   43 |        31 |        2 |           331 |                31 |          |
|       2 |   44 |        31 |        2 |           331 |                31 |          |
|       3 |   32 |        32 |        2 |           492 |                32 |          |
|       3 |   33 |        33 |        6 |           492 |                33 |          |
|       3 |   34 |        34 |        5 |           492 |                34 |          |
|       3 |   35 |        35 |        6 |           492 |                35 |          |
|       3 |   36 |        35 |        6 |           492 |                35 |          |
|       3 |   37 |        35 |        6 |           492 |                35 |          |
|       3 |   38 |        35 |        6 |           493 |                35 |          |
|       3 |   39 |        35 |        6 |           492 |                35 |          |
|       4 |  219 |       219 |       18 |            65 |               219 |          |
|       4 |  220 |       220 |       16 |            65 |               220 |          |
|       4 |  221 |       220 |        1 |           246 |               220 |          |
|       4 |  222 |       220 |       16 |            65 |               220 |          |
|       4 |  223 |       223 |       18 |            65 |               223 |          |
|       5 |   39 |        39 |       10 |           113 |                39 |          |
|       5 |   40 |        40 |        9 |           113 |                40 |          |
|       5 |   41 |        40 |       10 |           112 |                40 |          |
|       5 |   42 |        42 |        9 |           112 |                42 |          |
|       5 |   43 |        42 |        1 |           241 |                42 |          |
|       5 |   44 |        44 |        2 |           241 |                44 |          |
|       5 |   45 |        44 |        2 |           241 |                44 |          |
|       5 |   46 |        46 |        1 |           241 |                46 |          |
|       5 |   47 |        46 |        1 |           241 |                46 |          |
|       5 |   48 |        48 |        2 |           241 |                48 |          |
|       6 |   46 |        46 |       14 |           184 |                46 |          |
|       6 |   47 |        46 |       14 |           183 |                46 |          |
|       6 |   48 |        46 |       14 |           183 |                46 |          |
|       6 |   49 |        46 |        1 |           184 |                49 | X        |
|       6 |   50 |        46 |       15 |           183 |                49 | X        |
|       6 |   51 |        46 |       15 |           183 |                49 | X        |
|       7 |  148 |       148 |        6 |           725 |               148 |          |
|       7 |  149 |       149 |        5 |           725 |               149 |          |
|       7 |  150 |       149 |        5 |           725 |               149 |          |
|       7 |  151 |       151 |        6 |           725 |               151 |          |
|       7 |  152 |       151 |        6 |           723 |               151 |          |
|       7 |  153 |       151 |        6 |           724 |               151 |          |
|       8 |  150 |       150 |        2 |           221 |               150 |          |
|       8 |  151 |       151 |        1 |           221 |               151 |          |
|       8 |  152 |       152 |        2 |           221 |               152 |          |
|       8 |  153 |       152 |        2 |           221 |               152 |          |
|       8 |  154 |       152 |        1 |           222 |               152 |          |
|       9 |  122 |       122 |        3 |           462 |               122 |          |
|       9 |  123 |       123 |        2 |           462 |               123 |          |
|       9 |  124 |       123 |        2 |           463 |               123 |          |
|       9 |  125 |       123 |        2 |           463 |               123 |          |
|      10 |   36 |        36 |       10 |           617 |                36 |          |
|      10 |   37 |        37 |        9 |           617 |                37 |          |
|      10 |   38 |        37 |       10 |           618 |                37 |          |
|      10 |   39 |        39 |        9 |           618 |                39 |          |
|      11 |   97 |        97 |       22 |            91 |                97 |          |
|      11 |   98 |        97 |       22 |            91 |                97 |          |
|      11 |   99 |        99 |       21 |            91 |                99 |          |
|      11 |  100 |       100 |       22 |            91 |               100 |          |
|      11 |  101 |       100 |       14 |            92 |               100 |          |
|      12 |  108 |       108 |       22 |           463 |               108 |          |
|      12 |  109 |       108 |       23 |           460 |               108 |          |
|      12 |  110 |       108 |       23 |           460 |               108 |          |
|      12 |  111 |       108 |       22 |           461 |               108 |          |
|      12 |  112 |       108 |       22 |           461 |               108 |          |
|      12 |  113 |       113 |       21 |           462 |               113 |          |
|      12 |  114 |       113 |       21 |           462 |               113 |          |
|      12 |  115 |       113 |       22 |           463 |               113 |          |
|      13 |  156 |       156 |       11 |           462 |               156 |          |
|      13 |  157 |       157 |       10 |           462 |               157 |          |
|      13 |  158 |       157 |       10 |           463 |               157 |          |
|      13 |  159 |       157 |       10 |           463 |               157 |          |
|      14 |   20 |        20 |        8 |           283 |                20 |          |
|      14 |   21 |        21 |        7 |           283 |                21 |          |
|      14 |   22 |        22 |        9 |           283 |                22 |          |
|      14 |   23 |        23 |        8 |           283 |                23 |          |
|      14 |   24 |        24 |       11 |           283 |                24 |          |
|      14 |   25 |        25 |       10 |           283 |                25 |          |
|      14 |   26 |        26 |       12 |           283 |                26 |          |
|      14 |   27 |        27 |       11 |           283 |                27 |          |
|      14 |   28 |        27 |        4 |           282 |                27 |          |
|      14 |   29 |        27 |        4 |           282 |                27 |          |
|      15 |  105 |       105 |        2 |           418 |               105 |          |
|      15 |  106 |       106 |        1 |           418 |               106 |          |
|      15 |  107 |       106 |        1 |           418 |               106 |          |
|      15 |  108 |       108 |        2 |           418 |               108 |          |
|      15 |  109 |       109 |        1 |           418 |               109 |          |
|      15 |  110 |       109 |        1 |           418 |               109 |          |
|      15 |  111 |       111 |        2 |           418 |               111 |          |
|      16 |   57 |        57 |       13 |           776 |                57 |          |
|      16 |   58 |        57 |       14 |           777 |                57 |          |
|      16 |   59 |        59 |       15 |           777 |                59 |          |
|      16 |   60 |        59 |       15 |           777 |                59 |          |
|      16 |   61 |        61 |       14 |           776 |                61 |          |
|      17 |    9 |         9 |        3 |           771 |                 9 |          |
|      17 |   10 |         9 |        3 |           771 |                 9 |          |
|      17 |   11 |         9 |        3 |           771 |                 9 |          |
|      17 |   12 |         9 |        3 |           771 |                 9 |          |
|      17 |   13 |         9 |        1 |           772 |                 9 |          |
|      17 |   14 |         9 |        1 |           772 |                 9 |          |
|      18 |   81 |        81 |       21 |           267 |                81 |          |
|      18 |   82 |        82 |       22 |           267 |                82 |          |
|      18 |   83 |        83 |       21 |           267 |                83 |          |
|      18 |   84 |        83 |       21 |           267 |                83 |          |
|      18 |   85 |        85 |       22 |           267 |                85 |          |
|      18 |   86 |        85 |       22 |           267 |                85 |          |
|      18 |   87 |        87 |       21 |           267 |                87 |          |
+---------+------+-----------+----------+---------------+-------------------+----------+

【讨论】:

谢谢,非常有趣,但有一个明显的小错误:Slot 59 & 60 应该有 SlotGroup 59 而不是 58,Slot 63 & 64 也是如此。此外,它在更复杂的情况下会失败(多个在同一个 SlotGroup 中跳转)。这似乎是我正在寻找的正确方向,让我们看看我们是否可以让它完美地工作:) @Simone 更新了我的答案,感谢您的澄清。 我仍在努力,但不幸的是,您的解决方案并不完全正确;至少有两种组合仍然存在问题;请检查我编辑的问题 对不起,但我担心这不正确:插槽 42 仍然有插槽组 39,而我的要求是将其设置为 42。我错过了什么吗? 我按照您的提示进行操作,但仍有一些极端情况 :(,添加了它们

以上是关于如何将自引用的复杂游标转换为更高效的 SQL 代码? CTE、交叉应用还是其他?的主要内容,如果未能解决你的问题,请参考以下文章

将引用游标转换为 pl-sql 中的表类型

Oracle PL/SQL 引用游标如何

有没有办法选择引用游标的内容作为 SQL Select 语句的一部分?

PL/SQL 打印出存储过程返回的引用游标

如何检查 ref 游标是不是从 pl/sql 过程返回数据

PL/SQL 在游标中引用另一个游标?