实现 SQL 嵌套游标的最佳方法是什么

What is the best way to implement a SQL Nested Cursor

有人可以告诉我使用提供的数据集实现嵌套游标的最佳方法吗?

正如您将看到的,已经有一个 Cursor 查找 #TMP_CODE1 中列出的值,如果匹配则执行 select 语句并将结果插入到输出 table.

我正在尝试使用嵌套游标对存储在#TMP_CODE2.

中的值复制相同的过程

我想打印@Numbers 的方式与将@Letters 插入到下面的#Output table 中的方式相同:

  PRINT @Letters;
  INSERT INTO #Output ([Dummy Column1], [Dummy Column2]) VALUES ('Letters:', @Letters)
  INSERT INTO #Output ([Dummy Column1]) VALUES ('') 

每行组合在一起,代码显示在每个结果集上方。

只有在#TMP_CODE1 和#TMP_CODE2 临时 table 中列出的值才能插入输出 table。

DROP TABLE IF EXISTS #TMP_CODE1
CREATE TABLE #TMP_CODE1(Letters varchar(3));
INSERT INTO #TMP_CODE1(Letters) VALUES 
  ('AAA'),('BBB'),('CCC'),('DDD'),('EEE'),('FFF');

DROP TABLE IF EXISTS #TMP_CODE2
CREATE TABLE #TMP_CODE2(Numbers varchar(3));
INSERT INTO #TMP_CODE2(Numbers) VALUES 
  ('111'),('222'),('333'),('444'),('555'),('666');

DROP TABLE IF EXISTS #Input
CREATE TABLE #Input (CODE1 varchar(3), [Dummy Column1] varchar (15), 
[Dummy Column2] varchar (15), CODE2 varchar(3), [Dummy Column3] varchar (15),
[Dummy Column4] varchar (15));

DROP TABLE IF EXISTS #Output
CREATE TABLE #Output (CODE1 varchar(3), [Dummy Column1] varchar (15), 
[Dummy Column2] varchar (15), CODE2 varchar(3), [Dummy Column3] varchar (15),
[Dummy Column4] varchar (15));

INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('AAA', 'DUMMY DATA 1 1', 'DUMMY DATA 2 1', '111', 'DUMMY DATA 3 1', 'DUMMY DATA 4 1')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('AAA', 'DUMMY DATA 1 2', 'DUMMY DATA 2 2', '111', 'DUMMY DATA 3 2', 'DUMMY DATA 4 2')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('AAA', 'DUMMY DATA 1 3', 'DUMMY DATA 2 3', '111', 'DUMMY DATA 3 3', 'DUMMY DATA 4 3')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('AAA', 'DUMMY DATA 1 4', 'DUMMY DATA 2 4', '222', 'DUMMY DATA 3 4', 'DUMMY DATA 4 4')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('AAA', 'DUMMY DATA 1 5', 'DUMMY DATA 2 5', '333', 'DUMMY DATA 3 5', 'DUMMY DATA 4 5')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('AAA', 'DUMMY DATA 1 6', 'DUMMY DATA 2 6', '555', 'DUMMY DATA 3 6', 'DUMMY DATA 4 6')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 7', 'DUMMY DATA 2 7', '222', 'DUMMY DATA 3 7', 'DUMMY DATA 4 7')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 8', 'DUMMY DATA 2 8', '111', 'DUMMY DATA 3 8', 'DUMMY DATA 4 8')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 9', 'DUMMY DATA 2 9', '555', 'DUMMY DATA 3 9', 'DUMMY DATA 4 9')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 10', 'DUMMY DATA 2 10', '444', 'DUMMY DATA 3 10', 'DUMMY DATA 4 10')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 11', 'DUMMY DATA 2 11', '777', 'DUMMY DATA 3 11', 'DUMMY DATA 4 11')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 12', 'DUMMY DATA 2 12', '888', 'DUMMY DATA 3 12', 'DUMMY DATA 4 12')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 13', 'DUMMY DATA 2 13', '222', 'DUMMY DATA 3 13', 'DUMMY DATA 4 13')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 14', 'DUMMY DATA 2 14', '111', 'DUMMY DATA 3 14', 'DUMMY DATA 4 14')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 15', 'DUMMY DATA 2 15', '222', 'DUMMY DATA 3 15', 'DUMMY DATA 4 15')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('BBB', 'DUMMY DATA 1 16', 'DUMMY DATA 2 16', '666', 'DUMMY DATA 3 16', 'DUMMY DATA 4 16')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('CCC', 'DUMMY DATA 1 17', 'DUMMY DATA 2 17', '111', 'DUMMY DATA 3 17', 'DUMMY DATA 4 17')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('CCC', 'DUMMY DATA 1 18', 'DUMMY DATA 2 18', '111', 'DUMMY DATA 3 18', 'DUMMY DATA 4 18')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('DDD', 'DUMMY DATA 1 19', 'DUMMY DATA 2 19', '111', 'DUMMY DATA 3 19', 'DUMMY DATA 4 19')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('DDD', 'DUMMY DATA 1 20', 'DUMMY DATA 2 20', '222', 'DUMMY DATA 3 20', 'DUMMY DATA 4 20')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('DDD', 'DUMMY DATA 1 21', 'DUMMY DATA 2 21', '333', 'DUMMY DATA 3 21', 'DUMMY DATA 4 21')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('DDD', 'DUMMY DATA 1 22', 'DUMMY DATA 2 22', '555', 'DUMMY DATA 3 22', 'DUMMY DATA 4 22')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('EEE', 'DUMMY DATA 1 23', 'DUMMY DATA 2 23', '222', 'DUMMY DATA 3 23', 'DUMMY DATA 4 23')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('EEE', 'DUMMY DATA 1 24', 'DUMMY DATA 2 24', '111', 'DUMMY DATA 3 24', 'DUMMY DATA 4 24')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('EEE', 'DUMMY DATA 1 25', 'DUMMY DATA 2 25', '555', 'DUMMY DATA 3 25', 'DUMMY DATA 4 25')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('EEE', 'DUMMY DATA 1 26', 'DUMMY DATA 2 26', '444', 'DUMMY DATA 3 26', 'DUMMY DATA 4 26')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('EEE', 'DUMMY DATA 1 27', 'DUMMY DATA 2 27', '777', 'DUMMY DATA 3 27', 'DUMMY DATA 4 27')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('FFF', 'DUMMY DATA 1 28', 'DUMMY DATA 2 28', '888', 'DUMMY DATA 3 28', 'DUMMY DATA 4 28')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('FFF', 'DUMMY DATA 1 29', 'DUMMY DATA 2 29', '222', 'DUMMY DATA 3 29', 'DUMMY DATA 4 29')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('FFF', 'DUMMY DATA 1 30', 'DUMMY DATA 2 30', '111', 'DUMMY DATA 3 30', 'DUMMY DATA 4 30')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('FFF', 'DUMMY DATA 1 31', 'DUMMY DATA 2 31', '222', 'DUMMY DATA 3 31', 'DUMMY DATA 4 31')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('GGG', 'DUMMY DATA 1 32', 'DUMMY DATA 2 32', '666', 'DUMMY DATA 3 32', 'DUMMY DATA 4 32')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('GGG', 'DUMMY DATA 1 33', 'DUMMY DATA 2 33', '222', 'DUMMY DATA 3 33', 'DUMMY DATA 4 33')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('GGG', 'DUMMY DATA 1 34', 'DUMMY DATA 2 34', '111', 'DUMMY DATA 3 34', 'DUMMY DATA 4 34')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('GGG', 'DUMMY DATA 1 35', 'DUMMY DATA 2 35', '555', 'DUMMY DATA 3 35', 'DUMMY DATA 4 35')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('HHH', 'DUMMY DATA 1 36', 'DUMMY DATA 2 36', '888', 'DUMMY DATA 3 36', 'DUMMY DATA 4 36')
INSERT INTO #Input (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3], [Dummy Column4]) VALUES ('HHH', 'DUMMY DATA 1 37', 'DUMMY DATA 2 37', '555', 'DUMMY DATA 3 37', 'DUMMY DATA 4 37')
  
DECLARE @Letters varchar(3), @c cursor;
    
SET @c = cursor LOCAL FAST_FORWARD
    FOR SELECT Letters FROM #TMP_CODE1;

OPEN @c;
FETCH NEXT FROM @c INTO @Letters;

WHILE @@FETCH_STATUS = 0
BEGIN

  PRINT @Letters;
  INSERT INTO #Output ([Dummy Column1], [Dummy Column2]) VALUES ('Letters:', @Letters)
  INSERT INTO #Output ([Dummy Column1]) VALUES ('')

  INSERT INTO #Output (CODE1, [Dummy Column1], [Dummy Column2], CODE2, [Dummy Column3],[Dummy Column4])
  SELECT * FROM #Input WHERE CODE1 = @Letters

  FETCH NEXT FROM @c INTO @Letters;

END

SELECT * FROM #Output

所以我希望实现的结构是这样的:

这仅适用于 AAA,我希望能够以这种格式格式化示例代码中提供的所有数据。

我正在使用 SQL 服务器,希望能以标准 SQL 的方式回答问题。

谢谢

我先说这个真的应该在表示层完成,而不是在SQL。

尽管如此,您实际上可以按照您想要的顺序获取您想要的所有行,小心使用 GROUPING SETSORDER BY:

SELECT
  CODE1           = CASE WHEN GROUPING(i.[Dummy Column1]) = 0 THEN CODE1 END,
  [Dummy Column1] = CASE WHEN GROUPING(i.CODE2) = 1 AND GROUPING(i.[Dummy Column1]) = 1
                           THEN 'Letters'
                         WHEN GROUPING(i.[Dummy Column1]) = 1
                           THEN 'Numbers'
                         ELSE i.[Dummy Column1] END,
  [Dummy Column2] = CASE WHEN GROUPING(i.CODE2) = 1 AND GROUPING(i.[Dummy Column1]) = 1
                           THEN i.CODE1
                         WHEN GROUPING(i.[Dummy Column1]) = 1
                           THEN i.CODE2
                         ELSE i.[Dummy Column1] END,
  CODE2           = CASE WHEN GROUPING(i.[Dummy Column1]) = 0 THEN CODE2 END,
  i.[Dummy Column3],
  i.[Dummy Column4]
FROM #Input i
GROUP BY GROUPING SETS (
    (i.CODE1),
    (i.CODE1, i.CODE2),
    (i.CODE1, i.CODE2, i.[Dummy Column1], i.[Dummy Column2], i.[Dummy Column3], i.[Dummy Column4])
)
ORDER BY
  i.CODE1,
  GROUPING(i.CODE2) DESC,
  i.CODE2,
  GROUPING(i.[Dummy Column1]) DESC;

db<>fiddle

GROUPING SETS可以return小计和总计。它比 ROLLUP.

更灵活

GROUPING() 函数告诉您某列是否已在该特定行中分组。您可以在 ORDER BY 中使用它来使总计行位于正确的位置。然后你可以在 SELECT 中使用它来区分这些行。

  • Mind your data types. Some columns may not be compatible with each other so you may need to cast.
  • Be careful with the ORDER BY, if you don't specify table aliases on the columns then it will sort by the final SELECT value, rather than the actual column value