如何按编号读取数据

时间:2018-08-02 23:21:43

标签: sql sql-server tsql

我有一个包含数字的字段,例如下面#Numbers中的示例。 #Numbers中每行中的每个数字都相关 包含在#Area表中的许多不同值中。

我需要使用每一行中的每个数字来建立从#Numbers到#Area的关系。

CREATE TABLE #Numbers
(
    Number int
)

INSERT INTO #Numbers
(
    Number
)

SELECT 102 UNION
SELECT 1 UNION
SELECT 2 UNION

select * from #Numbers

CREATE TABLE #Area
(
    Number int,
    Area varchar(50)
)

INSERT INTO #Area
(
    Number,
    Area
)
SELECT 0,'Area1' UNION
SELECT 1,'Area2' UNION
SELECT 1,'Area3' UNION
SELECT 1,'Area5' UNION
SELECT 1,'Area8' UNION
SELECT 1,'Area9' UNION
SELECT 2,'Area12' UNION
SELECT 2,'Area43' UNION
SELECT 2,'Area25' UNION

select * from #Area

它将为102返回以下内容:

102,Area2    
102,Area3    
102,Area5    
102,Area8    
102,Area9    
102,Area1     
102,Area12    
102,Area43    
102,Area25

对于1,它将返回:

1,Area2    
1,Area3    
1,Area5    
1,Area8    
1,Area9

对于2,它将返回:

2,Area12    
2,Area43
2,Area25

请注意数字如何与各个区域匹配,并相应地返回值。

4 个答案:

答案 0 :(得分:3)

好吧,OP已经标记了一个答案,甚至得到了投票。也许他不会读这本书,但是这是使用直接简单选择的另一种选择,(根据EP),这似乎使用了很多资源:

SELECT *
FROM #Numbers t1
LEFT JOIN #Area t2 ON CONVERT(VARCHAR(10), t1.Number) like '%' + CONVERT(CHAR(1), t2.Number) + '%'
GO
  

注意!根据执行计划,此解决方案仅使用27%,而选定的答案(由Squirrel编写)使用73%,但是执行计划有时会误导您, 您还应该使用真实的表结构和真实的数据检查IO和TIME统计信息。

答案 1 :(得分:2)

看来您需要从#Number中提取单个数字,然后将其用于加入#Area

; with tally as
(
    select  n = 1
    union all
    select  n = n + 1
    from    tally
    where   n < 10
)
select  n.Number, a.Area
from    #Numbers n
        cross apply
        (
            -- here it convert n.Number to string
            -- then extract 1 digit
            -- and finally convert back to integer
            select  num = convert(int, 
                                  substring(convert(varchar(10), n.Number),
                                            t.n, 
                                            1) 
                                  )
            from    tally t
            where   t.n <= len(convert(varchar(10), n.Number))
        ) d
        inner join #Area a  on  d.num = a.Number
order by n.Number

或者,如果您更喜欢用算术而不是字符串

; with Num as
(
    select  Number, n = 0, Num = Number / power(10, 0) % 10
    from    #Numbers

    union all

    select  Number, n = n + 1, Num = Number / power(10, n + 1) % 10
    from    Num
    where   Number  > power(10, n + 1)
)
select  n.Number, a.Area
from    Num n
    inner join #Area a  on  n.Num   = a.Number
order by n.Number

答案 2 :(得分:0)

这是我的主意。从理论上讲,它应该起作用。 有一个带有值的表(临时表或永久表)及其转换

IE。

ID   value
1    Area1, Area2, Area7, Area8, Area15
2    Area28, Area35

在每一行中各加一个特殊字符。使用带有该字符的string_split之类的函数将其转换为值列。

例如0123将类似于0 | 1 | 2 | 3,当您通过string_split运行它时,您将得到

0
1
2
3

现在将每个值添加到您的查询表中并返回值。

现在您有了一行,其中包含所需的所有值。使用另一个函数,例如STUFF FOR XML,并将这些值放回到单列中。

这听起来效率不高..但这是实现您所期望的一种方法..

另一种方法是进行replace() ..但这很混乱!

答案 3 :(得分:0)

创建第三个表n,该表包含一个列,也称为n,该列包含从1到您的数字中最大位数的整数。如果愿意,将其设置为1000,没关系。然后:

select #numbers.number, substring(convert(varchar,#numbers.number),n,1) as chr, Area 
from #numbers
join n on n>0 and n <=len(convert(varchar,number))
join #area on #area.number=substring(convert(varchar,#numbers.number),n,1)

中间的一栏chr只是在这里向您展示它在做什么,并且将从最终结果中删除。