May 13, 2005 at 7:25 am
create table #temp
(product_id int not null,
prod_desc char(1) null)
insert into #temp
select 1, 'A'
insert into #temp
select 1, 'B'
insert into #temp
select 1, 'C'
insert into #temp
select 2, 'D'
insert into #temp
select 2, 'E'
insert into #temp
select 2, 'F'
select *
from #temp
product_id prod_desc
----------- ---------
1 A
1 B
1 C
2 D
2 E
2 F
Instead of dispaying as represented above, I need to display this as
product_id prod_desc
----------- ---------
1 A, B, C
2 D, E, F
How can I achieve this?
Thanks.
May 13, 2005 at 7:39 am
http://sqljunkies.com/WebLog/amachanic/archive/2004/11/10/5065.aspx?Pending=true
--
Frank Kalis
Microsoft SQL Server MVP
Webmaster: http://www.insidesql.org/blogs
My blog: http://www.insidesql.org/blogs/frankkalis/[/url]
May 13, 2005 at 8:04 am
set nocount on
create table #temp
(product_id int not null,
prod_desc char(1) null)
insert into #temp
select 1, 'A'
insert into #temp
select 1, 'B'
insert into #temp
select 1, 'C'
insert into #temp
select 2, 'D'
insert into #temp
select 2, 'E'
insert into #temp
select 2, 'F'
DECLARE @Output VARCHAR(8000)
SET @Output = ''
SELECT @Output = CASE @Output
WHEN '' THEN prod_desc
ELSE @Output + ', ' + prod_desc
END
FROM #temp
WHERE Product_id = 1
ORDER BY product_id
print @output
--should this out not be A, B, C
--however i received an OUTPUT of just A
May 13, 2005 at 8:08 am
SELECT @Output = @Output + CASE @Output
WHEN '' THEN prod_desc
ELSE @Output + ', ' + prod_desc
END
FROM #temp
WHERE Product_id = 1
ORDER BY product_id
May 13, 2005 at 8:10 am
still produced A? missing something....
sql query analyzer version 8.00.194
May 13, 2005 at 8:35 am
I tried the first script as below - picks only one description - am I missing something?
CREATE FUNCTION dbo.concatdesc(@product_id INT)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @Output VARCHAR(8000)
SET @Output = ''
SELECT @Output = @Output + CASE @Output
WHEN '' THEN prod_desc
ELSE @Output + ', ' + prod_desc
END
FROM prod
WHERE product_id = @product_id
ORDER BY prod_desc
RETURN @Output
END
GO
SELECT DISTINCT product_id, prod_desc = dbo.Concatdesc(product_id)
FROM prod
ORDER BY product_id
product_id prod_desc 1 A 2 D
Thanks
May 13, 2005 at 8:39 am
I tried the second method suggested - this pulls all the descriptions - however, has it in the reverse order - C,B,A instead of A, B, C - any ideas?
The following is what I tried.
CREATE TABLE #DescConcat
( product_id INT NOT NULL ,
prod_desc VARCHAR(8000) NULL,
Ident INT IDENTITY(1,1) NOT NULL PRIMARY KEY
)
INSERT #DescConcat (product_id, prod_desc)
SELECT product_id, prod_desc
FROM prod
ORDER BY product_id, prod_desc
DECLARE @prod_desc VARCHAR(8000), @product_id INT
SET @prod_desc = ''
SET @product_id = ''
UPDATE #DescConcat
SET @prod_desc = prod_desc =CASE WHEN @product_id = product_id
THEN prod_desc + ', ' + @prod_desc
ELSE prod_desc END,
@product_id = product_id
SELECT product_id, MAX(prod_desc)
FROM #DescConcat
GROUP BY product_id
product_id prod_desc 1 C, B, A
2 F, E, D
Thanks
May 13, 2005 at 8:54 am
set nocount on
create table #temp
(product_id int not null,
prod_desc char(1) null)
insert into #temp
select 1, 'A'
insert into #temp
select 1, 'B'
insert into #temp
select 1, 'C'
insert into #temp
select 2, 'D'
insert into #temp
select 2, 'E'
insert into #temp
select 2, 'F'
DECLARE @Output VARCHAR(8000)
SET @Output = ''
SELECT @Output = @Output + prod_desc + ', '
FROM #temp
WHERE Product_id = 1
ORDER BY product_id
Select left(@Output, len(@Output) -1) as output
drop table #temp
May 13, 2005 at 9:49 am
I tried this without the UDF (basically the UDF is the second WHILE is the UDF). It looks long, but if you made the UDF, it should be relatively short...
CREATE TABLE #temp( product_id int NOT NULL,
prod_desc char(1) NULL)
INSERT INTO #temp VALUES( 1, 'A')
INSERT INTO #temp VALUES( 1, 'B')
INSERT INTO #temp VALUES( 1, 'C')
INSERT INTO #temp VALUES( 2, 'D')
INSERT INTO #temp VALUES( 2, 'E')
INSERT INTO #temp VALUES( 2, 'F')
DECLARE @Output varchar(8000),
@ProductDesc varchar(2000),
@ProductID int,
@MaxProductID int,
@Counter int,
@IDCounter int
SET @Output = ''
SELECT @ProductID = (SELECT MIN( product_id) FROM #temp)
SELECT @MaxProductID = (SELECT MAX( product_id) FROM #temp)
SELECT @ProductDesc = (SELECT MIN( prod_desc) FROM #temp
WHERE product_id = @ProductID)
SELECT @Counter = 1
SELECT @IDCounter = ( SELECT COUNT(*) FROM #temp
WHERE product_id = @ProductID)
CREATE TABLE #OutPut( ProductID int,
ProductDesc char(50))
WHILE @ProductID <= @MaxProductID
BEGIN
WHILE @Counter <= @IDCounter
BEGIN
IF LEN( @OutPut) < 1
BEGIN
SELECT @OutPut = @ProductDesc
END
ELSE
BEGIN
SELECT @Output = @OutPut + ', ' + @ProductDesc
END
SELECT @ProductDesc = (SELECT MIN( prod_desc) FROM #temp
WHERE product_id = @ProductID
AND prod_desc > @ProductDesc)
SELECT @Counter = @Counter + 1
END
INSERT INTO #OutPut VALUES( @ProductID, @Output)
SELECT @ProductID = (SELECT MIN( product_id) FROM #temp
WHERE product_id > @ProductID)
SELECT @IDCounter = ( SELECT COUNT(*) FROM #temp
WHERE product_id = @ProductID)
SELECT @ProductDesc = (SELECT MIN( prod_desc) FROM #temp
WHERE product_id = @ProductID)
SELECT @OutPut = ''
SELECT @Counter = 1
SELECT @IDCounter = ( SELECT COUNT(*) FROM #temp
WHERE product_id = @ProductID)
END
SELECT * FROM #OutPut
DROP TABLE #temp
DROP TABLE #OutPut
I wasn't born stupid - I had to study.
May 16, 2005 at 12:30 am
thanks remi, did not need to use the case statement. this is a pretty cool tip & trick in the bag
http://sqljunkies.com/WebLog/amachanic/archive/2004/11/10/5065.aspx?Pending=true
hi sheba, still use option 1 as referenced by frank (adam udf clocks good performance), but read remi's POST to make it work (remi removed the case statement - adam's udf might have been tested on a different sql server version but still is a notable tip)
cheers mate
May 16, 2005 at 8:14 am
I was able to get option 2 to work. However, what Remi suggested brings only one line of output - Farrell's method works without a glitch. How is the efficiency of this script when compared to option 1.
May 16, 2005 at 8:19 am
My version is meant to be used as a UDF. It's much easier to use and versatile that way.
May 16, 2005 at 9:23 am
set nocount on
create table #temp
(product_id int not null,
prod_desc char(1) null)
insert into #temp
select 1, 'A'
insert into #temp
select 1, 'B'
insert into #temp
select 1, 'C'
insert into #temp
select 2, 'D'
insert into #temp
select 2, 'E'
insert into #temp
select 2, 'F'
CREATE FUNCTION dbo.concatdesc(@product_id INT)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @Output VARCHAR(8000)
SET @Output = ''
SELECT @Output = @Output + prod_desc + ', '
FROM prod
WHERE product_id = @product_id
ORDER BY prod_desc
RETURN @Output
END
GO
SELECT DISTINCT product_id, prod_desc = left(dbo.Concatdesc(product_id),
len(dbo.Concatdesc(product_id))-1)
FROM prod
ORDER BY product_id
Remi's script incorporated in option 1, worked well. Thanks. I understand using an UDF is efficient - how does this compare to Farrell's method of using a WHILE loop.
May 16, 2005 at 12:17 pm
A WHILE loop will probably take longer, although the function will still have walk through each record to get the output you want.
I coded mine specifically so the function-like activity could be seen. I would recommend staying with Remi's function approach as you will find you will probably need other similar functions to process what you want. Functions are re-useable is coded well. My approach is a one time shot for that specific use.
I wasn't born stupid - I had to study.
Viewing 14 posts - 1 through 13 (of 13 total)
You must be logged in to reply to this topic. Login to reply