SQL获取电话号码序列

时间:2015-07-20 14:28:04

标签: sql sql-server sql-server-2008

我有一个名为PhoneNumbers的表,其中包含Phone和Range列,如下所示

enter image description here

这里在电话栏中我有一个电话号码,在范围栏中我有一系列的值我需要包含的电话号码。对于第一个电话号码9125678463,我需要包括电话号码,直到范围9125678465即(9125678463,9125678464,9125678465)。同样适用于其他电话号码。样本目的地表应该如下所示

enter image description here

我如何编写sql来获取它?

提前致谢

4 个答案:

答案 0 :(得分:1)

您可以像这样使用CTE:

;WITH CTE (PhoneNumbers, [Range], i) AS (
    SELECT CAST(Phone AS bigint), [Range], CAST(1 AS bigint)
    FROM yourTable
    UNION ALL
    SELECT CAST(PhoneNumbers + 1 AS bigint), [Range], i + 1
    FROM CTE
    WHERE (PhoneNumbers + 1) % 10000 <= [Range] 
)
SELECT PhoneNumbers
FROM CTE
ORDER BY PhoneNumbers

答案 1 :(得分:1)

以下是使用计数表的一个示例。在我的系统中,我将这组ctes视为一个视图,所以我再也不必写它了。

if OBJECT_ID('tempdb..#PhoneNumbers') is not null
    drop table #PhoneNumbers;

create table #PhoneNumbers
(
    Phone char(10)
    , Range smallint
) 

insert #PhoneNumbers
    select 9135678463, 8465 union all
    select 3279275678, 5679 union all
    select 6372938103, 8105;

WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS 
(
    SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)

select *
from #PhoneNumbers p
join cteTally t on t.N >= RIGHT(Phone, 4) and t.N <= Range
order by p.Phone

答案 2 :(得分:1)

我有一个经典方式的解决方案但是:它不需要递归,也不需要任何循环!即使你的范围长度为3或5,或者其他什么......它仍然有效。

首先我创建一个带有数字的表(在本例中为1到100万 - 你可以在TOP()子句中采用它):

SELECT TOP (1000000) n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
INTO dbo.Numbers
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);

CREATE UNIQUE CLUSTERED INDEX idx_numbers ON dbo.Numbers(n)
;

如果你有那张桌子,那很简单:

;WITH phonenumbers
AS
(
SELECT  phone,
        [range],
        CAST(RIGHT(phone,LEN([range])) AS INT) AS number_to_increase,
        CAST(LEFT(phone,LEN(phone)-LEN([range])) + REPLICATE('0',LEN([range])) AS BIGINT) AS base_number
FROM    PhoneNumbers
)

SELECT  p.base_number + num.n
FROM    phonenumbers p
        INNER JOIN dbo.Numbers num ON num.n BETWEEN p.number_to_increase AND p.[range]

您不必像这里一样使用CTE - 这只是为了更清楚地了解这种方法背后的想法。也许这适合你

答案 3 :(得分:0)

另一种方法:

--Creating dummy table
select '9999991234' phone, '1237' rang into #tbl
union
select '9999995689', '5692'

SELECT [phone] low
        ,(CAST(9999995689/10000 AS bigINT) * 10000  + [Rang]) high
 into #tbl1
 FROM #tbl

--Creating 'numbrs' to have numbers between 0 & 9999 i.e. max range

select (rn-1)rn
into #numbrs
from 
(select row_number() over (partition by null order by A.object_id) rn from sys.objects A 
cross join sys.objects B)A 
where rn between 0 and 9999

select (low + rn)phn from #numbrs cross join #tbl1
where (low + rn) between low and high