JOINING逗号分隔值

时间:2011-10-13 23:57:11

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

我有两张表格如下:

TABLE:CITY

CITY_ID CITY
----------------
1   London

2   Chicago

3   Newyork

4   Delhi


TABLE:TRAIN

TRAIN_ID CITY_TRAVELS
----------------------
1111           1,3

2222           4

3333           1,2

4444           2,3

我想写一个查询,它应该给出以下结果: TRAIN表中的CITY_TRAVELS也是VARCHAR类型 CITY表的CITY_ID和INT的类型。 查询结构将如何?

TRAIN_ID  CITY
-------------------------
1111     London,Newyork

2222     Delhi

3333     London,Chicago

4444     Chicago,Newyork

由于 萨蒂亚吉特

3 个答案:

答案 0 :(得分:5)

结构很糟糕,但你可以在一些UDF中解析逗号分隔的字符串,并使用子查询将数字连接到城市。希望文章"Split Function in Sql Server to break Comma-Separated Strings into Table"能帮到你!

答案 1 :(得分:4)

-- sample data
declare @City table
(
    CityID int,
    City varchar(50)
)

declare @Train table
(
    TrainID int,
    CityTravels varchar(50)
)

insert into @City 
select 1, 'London'
union all
select 2, 'Chicago'
union all
select 3, 'Newyork'
union all
select 4, 'Delhi'

insert into @Train
select 1111, '1,3'
union all
select 2222, '4'
union all
select 3333, '1,2'
union all
select 4444, '2,3'


-- solution
;with cte as
(
    select
        t1.TrainID, t2.City
    from
    (
        select
            TrainID, 
            -- t2.c - the xml tag that function nodes provides
            -- query('data(.)') gets the value of the tag
            CityID = cast(cast(t2.c.query('data(.)') as varchar) as int)
        from
        (
            select 
                TrainID,
                -- represent Cities list in the xml, 
                -- which is proper for xquery node function
                -- for example <root><a>1</a><a>2</a></root>
                CityTravelsXml = cast('<root><a>' + replace(CityTravels, ',', '</a><a>') + '</a></root>' as xml)
            from @Train
        ) t1
        -- xquery nodes function for each tag /root/a returns a separate row 
        -- with single column the represents the tag
        cross apply CityTravelsXml.nodes('/root/a') t2(c)
    ) t1
    join @City t2 on t1.CityID = t2.CityID
)


select
    TrainID,
    -- truncate the last comma
    Cities = case when Cities is not null then substring(Cities, 1, len(Cities) - 1) end
from
(
    select 
        TrainID, 
        Cities = 
        (
            -- for xml here concatenates strings in a column
            select 
                City + ',' 
            from cte t2 
            where t2.TrainID = t1.TrainID 
            for xml path('')
        ) 
    from @Train t1
) t

修改:删除了第二个解决方案,因为经过一些测试后,它显示出不合适的效果,尽管它对表格的引用较少。

答案 2 :(得分:1)

create database train

create table city(
city_id int identity(1,1),
city varchar(max)
)

create table train(
train_id int identity(1111,1111),
city_travels varchar(max)
)

insert into city values ('London');
insert into city values ('Chicago');
insert into city values ('NewYork');
insert into city values ('Delhi');

insert into train values ('1,3,4');
insert into train values ('4');
insert into train values ('1,2');
insert into train values ('1,2,3,4');

create table #train(
train_id int,
city varchar(max)
)
declare @count int, @id int,@first int;
declare @train_id int,@index int;
declare @city_travels varchar(max),@city_name varchar(max);
set @city_name=null;

declare train_cursor CURSOR for
select train_id,city_travels from train
open train_cursor
fetch next from train_cursor into @train_id,@city_travels

    while (@@fetch_status=0)
    begin
        set @first=0;
        set @index = charindex(',',@city_travels);
            if(@index!=0)
            begin
                if(@first=0)
                begin
                    set @id=convert (int,substring(@city_travels,1,@index-1));
                    set @city_travels=substring(@city_travels,@index+1,len(@city_travels));
                    set @city_name=((select city from city where city_id=@id)+',');
                    set @index=charindex(',',@city_travels);
                    set @first=1;
                end
                while(@index!=0)
                begin
                    set @id=convert (int,substring(@city_travels,1,@index-1));
                    set @city_travels=substring(@city_travels,@index+1,len(@city_travels));
                    set @index=charindex(',',@city_travels)
                    set @city_name=(@city_name+(select city from city where city_id=@id)+',');
                end
            set @id=convert (int,@city_travels);
            set @city_name=(@city_name+(select city from city where city_id=@id));
            insert into #train values (@train_id,@city_name);
            set @city_name=null;
            end
        else
        begin
            set @id=convert (int,@city_travels);
            set @city_name=(select city from city where city_id=@id);
            insert into #train values (@train_id,@city_name);
            set @city_name=null;
        end
    fetch next from train_cursor into @train_id,@city_travels
    end
select * from city;
select * from train;
select * from #train;
close train_cursor
deallocate train_cursor
truncate table #train