2

Let´s say I have two tables, "Garden" and "Flowers". There is a 1:n-relationship between these tables, because in a garden can be many flowers. Is it possible to write an SQL query which returns a result with the following structure:

GardenName     Flower1Name      Flower2Name .... (as long as there are entries in flowers)
myGarden        rose             tulip
2
  • 3
    What RDBMS? In general this is only possible if you define a fixed number of flower columns. Most RDBMSs have a limit on the number of columns as well. Commented Apr 5, 2011 at 15:32
  • Frederik - can you show your table structure? Commented Apr 5, 2011 at 15:50

4 Answers 4

8
CREATE TABLE #Garden (Id INT, Name VARCHAR(20))
INSERT INTO #Garden
SELECT 1, 'myGarden' UNION ALL
SELECT 2, 'yourGarden'

CREATE TABLE #Flowers (GardenId INT, Flower VARCHAR(20))
INSERT INTO #Flowers
SELECT  1, 'rose'  UNION ALL
SELECT  1, 'tulip'  UNION ALL
SELECT  2, 'thistle' 

DECLARE @ColList nvarchar(max)

SELECT @ColList = ISNULL(@ColList + ',','') + QUOTENAME('Flower' + CAST(ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS VARCHAR))
FROM #Flowers WHERE GardenId = (
SELECT TOP 1 GardenId
FROM #Flowers
ORDER BY COUNT(*) OVER (PARTITION BY GardenId) DESC

)

EXEC (N'
;WITH cte As
(
SELECT *, ''Flower'' + CAST(ROW_NUMBER() OVER (PARTITION BY GardenId ORDER BY (SELECT 0)) AS VARCHAR) RN
FROM #Flowers F
)
SELECT Name,' + @ColList + N'
FROM cte 
JOIN #Garden g ON g.Id = GardenId
PIVOT (MAX(Flower) FOR RN IN (' + @ColList + N')) Pvt')


DROP TABLE #Garden
DROP TABLE #Flowers

Returns

Name                 Flower1              Flower2
-------------------- -------------------- --------------------
myGarden             rose                 tulip
yourGarden           thistle              NULL
Sign up to request clarification or add additional context in comments.

2 Comments

I don't pretend to understand this, but I tested it and it seems to work. For each Garden it always fills the columns from the left and leaves the nulls on the right. Joe Enos was right about it not being pretty, but +1 for functionality!
Yep, that's a serious query right there. I'm right with you @Fillet, I don't really know what's going on there, but it's doing some cool stuff.
6

Look at using Pivot in SQL Server. Here is a good link that goes over how it works:

http://www.kodyaz.com/articles/t-sql-pivot-tables-in-sql-server-tutorial-with-examples.aspx

Ok, i think i got it working. Try this:

with temp as
(
    select 'myGarden' as name, 'test1' as flower
    union
    select 'myGarden','test2'
    union
    select 'myGarden','test5'
    union
    select 'abeGarden','test4'
    union
    select 'abeGarden','test5'
    union 
    select 'martinGarden', 'test2'
)

select* from temp
pivot
(
  max(flower)
  for flower in (test1,test2,test3,test4,test5)
) PivotTable

You could also make the values in the in clause dynamic. Since this is a CTE i can't in my example.

6 Comments

This doesn't do what the OP needs without some tricks though. You need some attribute to pivot on.
@martin, is right. I'm not sure what you would aggregate. I'm playing with it right now, if I find a solution I will add it.
@Abe - Maybe I'm biased but I think my answer is more what is needed!
But mine is so clean! Why do you think yours is better?
@Abe - Because yours does a matrix for every possible flower type and they all need to be known in advance. If I have begonias, orchids and tulips and you have roses, daffodils, and sunflowers yours will return a 6 column result set with those headings and a loads of Nulls. Mine will return a 3 column result set labelled Flower1 etc with the information about the flower contained in the row as per the OP's example.
|
2

Dynamic SQL with a cursor is the only way I can think of, and it won't be pretty.

Comments

0

If you only want the results for one garden at a time this would give you the data:

select gardenName from tblGarden where gardenid = 1 
Union ALL 
select tblFLowers.flowerName from tblFlowers where gardenid = 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.