Reputation: 3128
Imagine the following two tables:
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
)
Now I want to select all the rows from MainTable
, while combining all the rows that match each MainId
from OtherTable
into a single field in the result set.
Imagine the data:
MainTable:
1, 'Hi'
2, 'What'
OtherTable:
1, 'Fish', 1
1, 'Horse', 0
2, 'Fish', 0
I want a result set like this:
MainId, Data, Others
1, 'Hi', 'Fish=1,Horse=0'
2, 'What', 'Fish=0'
What is the most elegant way to do this?
(Don't worry about the comma being in front or at the end of the resulting string.)
Upvotes: 0
Views: 268
Reputation: 3128
Well, here is how I implemented it in Sybase 13.x. This code has the advantage of not being limited to a number of Name
s.
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
But it does have the disadvantage of using a cursor and a working table, which can - at least with a lot of data - make the whole process slow.
Upvotes: 0
Reputation: 1269633
There is no really elegant way to do this in Sybase. Here is one method, though:
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
That is, it enumerates the values in the second table. It then does conditional aggregation to get each value, using the stuff()
function to handle the extra comma. The above works for the first three values. If you want more, then you need to add more clauses.
Upvotes: 1