想象一下以下两个表:
create table MainTable (
MainId integer not null, -- This is the index
Data varchar(100) not null
)
create table OtherTable (
MainId integer not null, -- MainId, Name combined are the index.
Name varchar(100) not null,
Status tinyint not null
)
现在,我想从MainTable
中选择所有行,同时将MainId
中与每个OtherTable
匹配的所有行合并到结果集中的单个字段中。
想象一下数据:
MainTable:
1, 'Hi'
2, 'What'
OtherTable:
1, 'Fish', 1
1, 'Horse', 0
2, 'Fish', 0
我想要一个像这样的结果集:
MainId, Data, Others
1, 'Hi', 'Fish=1,Horse=0'
2, 'What', 'Fish=0'
最优雅的方法是什么?
(不要担心逗号位于结果字符串的前面或末尾。)
答案 0 :(得分:1)
在Sybase中没有非常优雅的方法。不过,这是一种方法:
select
mt.MainId,
mt.Data,
Others = stuff((
max(case when seqnum = 1 then ','+Name+'='+cast(status as varchar(255)) else '' end) +
max(case when seqnum = 2 then ','+Name+'='+cast(status as varchar(255)) else '' end) +
max(case when seqnum = 3 then ','+Name+'='+cast(status as varchar(255)) else '' end)
), 1, 1, '')
from MainTable mt
left outer join
(select
ot.*,
row_number() over (partition by MainId order by status desc) as seqnum
from OtherTable ot
) ot
on mt.MainId = ot.MainId
group by
mt.MainId, md.Data
也就是说,它枚举了第二个表中的值。然后使用stuff()
函数来处理额外的逗号,然后进行条件聚合以获取每个值。以上工作原理为前三个值。如果你想要更多,那么你需要添加更多的子句。
答案 1 :(得分:0)
好吧,这是我在Sybase 13.x中实现它的方式。此代码的优点是不限于Name
个。
create proc
as
declare
@MainId int,
@Name varchar(100),
@Status tinyint
create table #OtherTable (
MainId int not null,
CombStatus varchar(250) not null
)
declare OtherCursor cursor for
select
MainId, Name, Status
from
Others
open OtherCursor
fetch OtherCursor into @MainId, @Name, @Status
while (@@sqlstatus = 0) begin -- run until there are no more
if exists (select 1 from #OtherTable where MainId = @MainId) begin
update #OtherTable
set CombStatus = CombStatus + ','+@Name+'='+convert(varchar, Status)
where
MainId = @MainId
end else begin
insert into #OtherTable (MainId, CombStatus)
select
MainId = @MainId,
CombStatus = @Name+'='+convert(varchar, Status)
end
fetch OtherCursor into @MainId, @Name, @Status
end
close OtherCursor
select
mt.MainId,
mt.Data,
ot.CombStatus
from
MainTable mt
left join #OtherTable ot
on mt.MainId = ot.MainId
但它确实有使用游标和工作表的缺点,这可能 - 至少有大量数据 - 使整个过程变慢。