使用SQL Server表中的拖动数据填充缺少的ID

时间:2016-10-21 12:04:39

标签: sql sql-server sql-server-2008 common-table-expression

我正试图解决这个问题;我有一张这样的桌子:

SELECT [ID], [STRING] FROM Test

ID      STRING
38      Hi 38
39      Hi 39
42      Hi 42
46      Hi 46
47      Hi 47
49      Hi 49

TDL:

CREATE TABLE #Test     ([ID] int,[STRING] varchar(50)) ;

INSERT INTO #Test
    ([ID], [STRING])
VALUES
    (38, 'Hi 38'),
    (39, 'Hi 39'),
    (42, 'Hi 42'),
    (46, 'Hi 46'),
    (47, 'Hi 47'),
    (49, 'Hi 49')
;

IDINTSTRINGVARCHAR(50),我应该编写一个新的SELECT查询来获得此结果:

ID      STRING
38      Hi 38
39      Hi 39
40      Hi 39
41      Hi 39
42      Hi 42
43      Hi 42
44      Hi 42
45      Hi 42
46      Hi 46
47      Hi 47
48      Hi 47
49      Hi 49

填写渐进式ID并使用STRING的先前值作为新ID。

我尝试过使用CTE但没有结果。

4 个答案:

答案 0 :(得分:1)

在这里,我通过将差异复制到多个行来生成差异行,将它们转换为xml,外部应用实际表格。

DECLARE @Table TABLE
    (
      ID INT ,
      STRING VARCHAR(50)
    )
INSERT  INTO @Table
VALUES  ( 38, 'Hi 38' )
,       ( 39, 'Hi 39' )
,       ( 42, 'Hi 42' )
,       ( 46, 'Hi 46' )
,       ( 47, 'Hi 47' )
,       ( 49, 'Hi 49' );
WITH    cte
          AS ( SELECT   ID ,
                        STRING ,
                        CAST(REPLICATE('<k>1</k>',
                                       LEAD(ID) OVER ( ORDER BY ID ) - ID) AS XML) AS x
               FROM     @Table
             ),
        cte2
          AS ( SELECT   a.ID ,
                        a.STRING ,
                        ROW_NUMBER() OVER ( PARTITION BY a.ID ORDER BY ID )
                        - 1 AS ID2
               FROM     cte AS a
                        OUTER APPLY x.nodes('/k') t ( x )
             )
    SELECT  ID + ID2 AS ID ,
            STRING
    FROM    cte2 AS a
    ORDER BY a.ID

答案 1 :(得分:1)

对于SQL Server 2008

;WITH    id_rn ( id, string, rn )
          AS ( SELECT   id ,
                        string ,
                        ROW_NUMBER() OVER ( ORDER BY id )
               FROM     t
             ),
        id_min_max ( min_id, max_id )
          AS ( SELECT   MIN(id) ,
                        MAX(id)
               FROM     t
             ),
        rows ( n )
          AS ( SELECT   min_id
               FROM     id_min_max
               UNION ALL
               SELECT   n + 1
               FROM     rows
               WHERE    n < ( SELECT    max_id
                              FROM      id_min_max
                            )
             )
    SELECT  COALESCE(r.n, i1.id) AS id ,
            i1.string AS string
    FROM    id_rn AS i1
            LEFT JOIN id_rn AS i2 ON i2.rn = i1.rn + 1
            LEFT JOIN rows AS r ON r.n BETWEEN i1.id AND i2.id - 1
    ORDER BY id
OPTION  ( MAXRECURSION 0 );
;WITH    id_occ ( id, string, #id_missing_occ )
          AS ( SELECT   id ,
                        string ,
                        LEAD(id) OVER ( ORDER BY id ) - id - 1
               FROM     t
             ),
        max_id_occ ( #max_generated_rows )
          AS ( SELECT   MAX(#id_missing_occ) + 1
               FROM     id_occ
             ),
        rows ( n )
          AS ( SELECT   1
               UNION ALL
               SELECT   n + 1
               FROM     rows
               WHERE    n < ( SELECT    #max_generated_rows
                              FROM      max_id_occ
                            )
             )
    SELECT  id + COALESCE(n - 1, 0) ,
            string
    FROM    id_occ AS i
            LEFT JOIN rows AS r ON r.n <= i.#id_missing_occ + 1
                                   AND #id_missing_occ > 0
OPTION  ( MAXRECURSION 0 );

答案 2 :(得分:0)

您必须使用足够大的Tally表来覆盖表中找到的所有ID值范围。使用this source中的Tally表,查询可能如下所示:

WITH Tally (n) AS
(
    -- 1000 rows
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
    CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
    CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
), Min_Max_CTE(min_id, max_id) AS
(
   SELECT MIN(ID) AS min_id, MAX(ID) AS max_id
   FROM mytable
)
SELECT ID, MAX(STRING) OVER (PARTITION BY grp) AS STRING
FROM (
   SELECT t1.n AS ID, t3.STRING,
          MAX(t3.ID) OVER (ORDER BY t1.n) AS grp
   FROM Tally As t1
   CROSS JOIN Min_Max_CTE AS t2
   LEFT JOIN mytable AS t3 ON t3.ID = t1.n
   WHERE t1.n BETWEEN t2.min_id AND t2.max_id) AS t

注意:上述查询适用于SQL Server 2012 +。

答案 3 :(得分:0)

试试这个:

IClass2