中断两列之间的行范围

时间:2015-08-05 21:11:12

标签: sql sql-server sql-server-2005

我有一张表如下

CREATE TABLE [dbo].[CODE](
    [BEG] [varchar](10) NOT NULL,
    [END] [varchar](10) NOT NULL,
    [EFF_BEG] [smalldatetime] NOT NULL
) ON [PRIMARY]

Insert into CODE select 'H0411', 'H0413', '01/01/2015'
Insert into CODE select 'J090', 'J093', '01/01/2015'

我想得到BEG和END中所有代码的列表,如下所示

Instance
-------
H0411
H0412
H0413
J090
J091
J092
J093

我有类似下面的内容,但它不适用于varchar列

WITH number_cte (n)
AS (
    SELECT n
    FROM (
        SELECT 0 n
        ) m

    UNION ALL

    SELECT n + 1 n
    FROM number_cte
    WHERE n < 2400
    )
SELECT BEG+n instance
    ,EFF_BEG
FROM CODE
JOIN number_cte ON BEG + n BETWEEN BEG
        AND END
WHERE BEG + n - 100 * floor((BEG + n) / 100) BETWEEN 0
        AND 59
ORDER BY 1
OPTION (MAXRECURSION 2401)

对此有何解决方案?感谢

1 个答案:

答案 0 :(得分:1)

实现此目的的一种方法是通过Numbers表或CTE,您可以加入CODE表,如下所示:

WITH NUMBERS AS ( -- change limit if needed
  SELECT TOP 10000 row_number() over(order by t1.number) as Number
  FROM master..spt_values t1 
    CROSS JOIN master..spt_values t2),
CODE_SPLIT AS
( SELECT 
    BEG, [END],
    SUBSTRING(BEG, 1, PATINDEX('%[1-9]%', BEG)-1) as FirstChars,
    CONVERT(int, SUBSTRING(BEG, 2, LEN(BEG) - 1)) as BegInt,
    CONVERT(int, SUBSTRING([END], 2, LEN([END]) - 1)) as EndInt
  FROM [dbo].[CODE]
)
SELECT c.*,
 c.FirstChars + CAST(n.Number as VARCHAR) as Result
FROM 
 CODE_SPLIT c INNER JOIN 
 NUMBERS n ON n.Number BETWEEN BegInt AND EndInt;

我已将输出中的所有字段留下以进行验证,结果位于Result列。

所做的主要假设是代码由两部分组成,具有相应的顺序:

  • 单个非数字字符;
  • 可以有前导零的数字。

要创建永久Numbers表,您可以使用以下代码:

CREATE TABLE NumbersTest (Number  int  not null)  
INSERT INTO NumbersTest(Number)
SELECT TOP 10000 row_number() over(order by t1.number) as N
FROM master..spt_values t1 
    CROSS JOIN master..spt_values t2;

有关正常工作的代码,请参阅此SQL Fiddle