SQL-列出记录之间的所有页面,同时保持ID键

时间:2019-03-14 00:12:15

标签: sql sql-server tsql

我正在尝试提出一种有用的方法,将文档的最后一页之间的所有页面都列出到新行中,同时将ID号作为键或交叉引用。我有几种获取页面之间的方法,但是我不确定如何以编程方式维护密钥。

示例输入:

First Page  Last Page  ID
ABC_001     ABC_004    1
ABC_005     ABC_005    2
ABC_006     ABC_010    3

最终结果:

All Pages  ID
ABC_001    1
ABC_002    1
ABC_003    1
ABC_004    1
ABC_005    2
ABC_006    3
ABC_007    3
ABC_008    3
ABC_009    3
ABC_010    3

非常感谢您的帮助。我正在使用SQL mgmt studio。

2 个答案:

答案 0 :(得分:2)

一种方法是建立一个数字表,其中包含您可能会在列内容中找到的数字列表:

CREATE TABLE numbers( idx INTEGER);
INSERT INTO numbers VALUES(1);
INSERT INTO numbers VALUES(2);
...
INSERT INTO numbers VALUES(10);

现在,假设所有页面值都有7个字符,最后3个数字,我们可以将JOIN表和numbers表一起SELECT CONCAT( SUBSTRING(t.First_Page, 1, 4), REPLICATE('0', 3 - LEN(n.idx)), n.idx ) AS [ALl Pages], t.id FROM mytable t INNER JOIN numbers n ON n.idx >= CAST(SUBSTRING(t.First_Page, 5, 3) AS int) AND n.idx <= CAST(SUBSTRING(t.Last_Page, 5, 3) AS int) 生成缺少的记录:

$ENV:ARM_SUBSCRIPTION_ID = ""
$ENV:ARM_CLIENT_ID       = ""
$ENV:ARM_CLIENT_SECRET   = "" # This should end with an '=' symbol
$ENV:ARM_TENANT_ID       = ""

demo on DB Fiddle 及其示例数据将返回:

ALl Pages | id
:-------- | -:
ABC_001   |  1
ABC_002   |  1
ABC_003   |  1
ABC_004   |  1
ABC_005   |  2
ABC_006   |  3
ABC_007   |  3
ABC_008   |  3
ABC_009   |  3
ABC_010   |  3

答案 1 :(得分:1)

要查找每个图书ID从首页到最后一页的所有页面,请将您的页码从STRING到INTEGER,然后在每个页码上添加+1,直到到达最后一页。

首先,使用TRY_CAST将原始表转换为具有Integer数据类型的表变量。

DECLARE @Book TABLE (
    [ID]        INT
   ,[FirstPage] INT
   ,[LastPage]  INT
)

INSERT INTO @Book
SELECT  [ID]
       ,TRY_CAST(RIGHT([FirstPage], 3) AS int) AS [FirstPage]
       ,TRY_CAST(RIGHT([LastPage], 3) AS int)  AS [LastPage]
FROM [YourOriginalTable]

使用变量设置页面可增加的最大页面数。这会将您的结果显示在正确的页面数之内。否则,您的表中的行将比您需要的多。

DECLARE @LastPage   INT 
SELECT @LastPage = MAX([LastPage]) FROM @Book

将三列表(ID,第一页,最后一页)转换为两列表(ID,Page)将需要UNPIVOT。

我们将UNPIVOT塞入CTE(公用表表达式:基本上是临时表的智能版本(如#TempTable或@TableVariable,但您只能使用一次,在某些情况下效率更高)情况)。

除了将您的[名字]和[姓氏]列的UNPIVOT放入一个高大的表中之外,我们还将使用UNION ALL附加每个ID的页码的所有其他组合。

;WITH BookCTE AS (
    SELECT [ID]
          ,[Page]
    FROM (SELECT [ID]
                ,[FirstPage]
                ,[LastPage]
          FROM @Book) AS bp
    UNPIVOT
    (
        [Page] FOR [Pages] IN ([FirstPage], [LastPage])
    ) AS up
    UNION ALL
    SELECT [ID], [Page] + 1 FROM BookCTE WHERE [Page] + 1 < @LastPage
)

现在,使用CTE以[ID]和[Page]的所有组合将数据以表格格式保存到@Book表中的最大页面,现在该将CTE与@Book表联接起来了。

SELECT DISTINCT
        cte.ID
       ,cte.Page
FROM BookCTE AS cte
    INNER JOIN @Book AS bk
        ON bk.ID = cte.ID
WHERE cte.Page <= bk.[LastPage]
ORDER BY
       cte.ID
      ,cte.Page
OPTION (MAXRECURSION 10000)

另请参阅:

注意:更新时将重新整合FirstPage和LastPage的字符串部分(我认为这是基于书名)。待命。