Dynamic pivot query in sql server - sql

I have a functioning pivot query for static column values which i want to convert for dynamic column values.
The query is :
with a as (
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as 'Month'
,dateadd(month,datediff(month,0,logged_datetime),0) as 'Year'
from requests
)
select * from (
select datepart(m,a.Month) as 'months',datepart(YEAR,a.Year) as 'years',a.request_id
from a ) ps
pivot (
count(request_id) for [years] in ([2008],[2009],[2010],[2011],[2012],[2013],[2014],[2015])
) as pvt
order by months
For the dynamic query written below I am getting errors like
Msg 207, Level 16, State 1, Line 5 Invalid column name '2010'. :
select distinct datepart(year,dateadd(month,datediff(month,0,logged_datetime),0)) as 'Yearz'
into #t
FROM requests
DECLARE #Dynamic AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(Yearz)
FROM (SELECT * from #t) AS Yea
SET #Dynamic =
N'
select * from (
select datepart(m,dateadd(month,datediff(month,0,logged_datetime),0)) as months,' + #ColumnName + ',request_id
from requests ) ps
pivot (
count(request_id) for [Years] in (' + #ColumnName + ')
) as pvt
order by months
'
EXEC sp_executesql #Dynamic

SAMPLE TABLE
SELECT * INTO #REQUESTS
FROM
(
SELECT 1 request_id, '2012-06-01' logged_datetime
UNION ALL
SELECT 2 request_id, '2012-05-01'
UNION ALL
SELECT 11 request_id, '2012-06-01'
UNION ALL
SELECT 12 request_id, '2012-05-01'
UNION ALL
SELECT 3 request_id, '2012-07-01'
UNION ALL
SELECT 4 request_id, '2013-09-01'
UNION ALL
SELECT 5 request_id, '2013-10-01'
UNION ALL
SELECT 6 request_id, '2014-01-01'
UNION ALL
SELECT 7 request_id, '2014-02-01'
UNION ALL
SELECT 8 request_id, '2014-03-01'
UNION ALL
SELECT 9 request_id, '2014-05-01'
UNION ALL
SELECT 10 request_id, '2015-11-01'
)TAB
QUERY
Get the column for years and order it in numeric order
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + CAST([YEAR] AS VARCHAR(4)) + ']', '[' + CAST([YEAR] AS VARCHAR(4)) + ']')
FROM (SELECT DISTINCT YEAR(dateadd(month,datediff(month,0,logged_datetime),0)) [YEAR] FROM #REQUESTS) PV
ORDER BY CAST([YEAR] AS INT)
Now pivot the query
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT * FROM
(
-- We will get the count for a year and number of request_id in that month here as CNT column
select DISTINCT datepart(m,a.Month) as ''months'',datepart(YEAR,a.Year) as ''years'',
COUNT(*) OVER(PARTITION BY datepart(YEAR,a.Year),datepart(m,a.Month)) CNT
from
(
select request_id, dateadd(month,datediff(month,0,logged_datetime),0) as ''Month''
,dateadd(month,datediff(month,0,logged_datetime),0) as ''Year''
from #requests
)a
) x
PIVOT
(
MIN(CNT)
FOR years IN (' + #cols + ')
) p
ORDER BY MONTHS;'
EXEC SP_EXECUTESQL #query
Click here to view the result

I think you need to wrap your dynamic column names using the QUOTENAME function:
See example here:

Related

Moving Complex Query Results to a Table

I have a complex query that cannot be saved as a view because of the DECLARE statements at the beginning of the query.
I would like to save the results of the query into a table.
I tried to insert the following statement to surround the whole query and also only around the SET #sql and EXEC(#sql).
Both caused errors that I could not resolve.
This is the query that produces the results I need:
DECLARE #sql VARCHAR(MAX)
DECLARE #colList VARCHAR(MAX)
--create dynamic list of columns
SELECT #colList = STUFF((SELECT + ',' + QUOTENAME(colName + CAST(CAST(Billing_Order AS INTEGER) AS VARCHAR))
FROM Credible_Client_Insurance_Raw_Data
CROSS APPLY
(SELECT 1 As Ord, 'Payer_ID' ColName
UNION ALL
SELECT 2 As Ord, 'Billing_Order'
UNION ALL
SELECT 3 As Ord, 'Insurance_ID'
UNION ALL
SELECT 4 As Ord, 'Group_No'
UNION ALL
SELECT 5 As Ord, 'Copay_Fee'
UNION ALL
SELECT 6 As Ord, 'Start_Date') v
GROUP BY colName, Ord, CAST(CAST(Billing_Order AS INTEGER) AS VARCHAR)
ORDER BY CAST(CAST(Billing_Order AS INTEGER) AS VARCHAR), Ord
FOR XML PAT(''), TYPE).value('/', 'VARCHAR(MAX)'), 1, 1, '')
--unpivot columns into rows and then apply pivot
SET #sql = 'SELECT Client_ID, ' + #colList + '
FROM
(SELECT
Client_ID, ColVal,
colName + CAST(CAST(Billing_Order AS INTEGER) AS VARCHAR) ColName
FROM Credible_Client_Insurance_Raw_Data
CROSS APPLY
(
SELECT Payer_ID As ColVal, ''Payer_ID'' ColName UNION ALL
SELECT Billing_Order, ''Billing_Order'' UNION ALL
SELECT Insurance_ID, ''Insurance_ID'' UNION ALL
SELECT Group_No, ''Group_No'' UNION ALL
SELECT CAST(Copay_Fee AS VARCHAR), ''Copay_Fee'' UNION ALL
SELECT CAST(Start_Date AS VARCHAR), ''Start_Date''
) v
) A
PIVOT
(
MAX(ColVal) FOR ColName IN (' + #colList + ')
) P1 '
EXEC(#sql)
I just want to INSERT the query's result set into a permanent table Credible_Client_Insurance_Data.
Is there any way to essentially perform a
INSERT INTO Credible_Client_Insurance_Data (Client_ID, etc.)
SELECT Client_ID, etc.
FROM query_results
Or some type of data insert into the table?
IF I'm understanding correctly, don't you just need to change the value of #sql to:
SET #sql = '
INSERT INTO Credible_Client_Insurance_Data (' + #colList + ')
SELECT Client_ID, ' + #colList + '
FROM
(
SELECT Client_ID, ColVal,
colName + CAST(CAST(Billing_Order AS INTEGER) AS VARCHAR) ColName
FROM Credible_Client_Insurance_Raw_Data
CROSS APPLY
(
SELECT Payer_ID As ColVal, ''Payer_ID'' ColName UNION ALL
SELECT Billing_Order, ''Billing_Order'' UNION ALL
SELECT Insurance_ID, ''Insurance_ID'' UNION ALL
SELECT Group_No, ''Group_No'' UNION ALL
SELECT CAST(Copay_Fee AS VARCHAR), ''Copay_Fee'' UNION ALL
SELECT CAST(Start_Date AS VARCHAR), ''Start_Date''
) v
) A
PIVOT
(
MAX(ColVal) FOR ColName IN (' + #colList + ')
) P1 ;';

Pivot table from horizontal to vertical

i have a following table of results:
What i want is a resulted table with following structure:
Is any posibility to do that with SQL?
Thanks in advance.
EDIT (SQL query with exampled temp table):
CREATE TABLE #FINAL_STACK
(
FB_DATE datetime,
FB_DESC VARCHAR(200)
)
INSERT INTO #FINAL_STACK(FB_DATE, FB_DESC)
SELECT '2017-03-09', 'D - FIZ: 1'
UNION
SELECT '2017-03-09', 'D - PRI: 1'
UNION
SELECT '2017-03-10', 'D - FIZ: 1'
UNION
SELECT '2017-03-10', 'D - PRI: 1'
UNION
SELECT '2017-03-13', 'D - FIZ: 2'
UNION
SELECT '2017-03-13', 'D - PRI: 1'
UNION
SELECT '2017-03-13', 'D - TEPAP: 1'
SELECT * FROM #FINAL_STACK
Try this:
DECLARE #DynammicTSQLStatement NVARCHAR(MAX)
,#DynamicPIVOTColumns NVARCHAR(MAX);
SET #DynamicPIVOTColumns = STUFF
(
(
SELECT ',[' + CAST([FB_DATE] AS VARCHAR(12)) + ']'
FROM #FINAL_STACK
GROUP BY [FB_DATE]
ORDER BY [FB_DATE]
FOR XML PATH('') ,TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET #DynammicTSQLStatement = N'
SELECT *
FROM
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY FB_DATE ORDER BY (SELECT 1)) AS RID
FROM #FINAL_STACK
) DS
PIVOT
(
MAX([FB_DESC]) FOR [FB_DATE] IN (' + #DynamicPIVOTColumns + ')
) PVT';
EXEC sp_executesql #DynammicTSQLStatement;
We need to perform dynamic pivot in order to be sure it will always work for different days. Also, note we are creating a row ID column using ROW_NUMBER in order to ensure all records for particular date are displayed. Otherwise, you will get only one value (for example the min or the max) depending on the PIVOT aggregate function.

Total sum wrong value in Dynamic Pivot

I have complicated query which works pretty good (MS SQL 2012). But it makes a mistake when sum up same price items. It count them correctly but only takes price once instead of taking them as a count number. It only appears when same item has same price and from same country. Here is my query ;
CREATE TABLE #ITEMS(ID INT,NAME VARCHAR(30))
INSERT INTO #ITEMS
SELECT 1, 'laptop'
UNION ALL
SELECT 2, 'phone'
UNION ALL
SELECT 3, 'playstation'
UNION ALL
SELECT 4, 'MacBook'
CREATE TABLE #Country(ID INT,NAME VARCHAR(30))
INSERT INTO #Country
SELECT 1, 'England'
UNION ALL
SELECT 2, 'Sweden'
UNION ALL
SELECT 3, 'Russia'
UNION ALL
SELECT 4, 'Italy'
CREATE TABLE [#Pre-Request](Id INT, countryId INT, ItemId INT)
INSERT INTO [#Pre-Request]
SELECT 1,1,3
UNION ALL
SELECT 2,2,1
UNION ALL
SELECT 3,2,2
UNION ALL
SELECT 4,3,3
UNION ALL
SELECT 5,3,3
UNION ALL
SELECT 6,2,3
CREATE TABLE #Offers(Id INT, PRICE VARCHAR(50))
INSERT INTO #Offers
SELECT 18,'257$'
UNION ALL
SELECT 19,'151$'
UNION ALL
SELECT 20,'424$'
UNION ALL
SELECT 21,'433$'
UNION ALL
SELECT 22,'151$'
CREATE TABLE #Request(Id INT, preReqId INT, requestStatus INT,winOfferId INT)
INSERT INTO #Request
SELECT 44, 1, 3, 18
UNION ALL
SELECT 11, 2, 4, 21
UNION ALL
SELECT 53, 3, 4, 20
UNION ALL
SELECT 87, 4, 3, 22
UNION ALL
SELECT 43, 5, 3, 19
UNION ALL
SELECT 43, 6, 2, Null
;WITH CTE AS
(
SELECT DISTINCT I.NAME ITEMNAME,C.NAME COUNTRYNAME
,CAST(REPLACE(TAB.PRICE,'$','')AS INT)PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN I.NAME END) OVER(PARTITION BY C.NAME,I.NAME) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
UNION
-- Used to select Item name and country that are not in Pre-request table and other tables
SELECT I.NAME ,C.NAME ,NULL,0
FROM #Items I
CROSS JOIN #COUNTRY C
)
,CTE2 AS
(
-- Find the sum for number of items
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME,
SUM(PRICE)PRICE
FROM CTE
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
,CTE3 AS
(
-- Find the sum of PRICE
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME--,CNTITEM
,SUM(CNTITEM)CNTITEM
FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,CNTITEM
FROM CTE
)TAB
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
SELECT C2.*,C3.CNTITEM,
CAST(C3.CNTITEM AS VARCHAR(20))+'x'+' ' + CAST(C2.PRICE AS VARCHAR(20))+'$' NEWCOL
INTO #NEWTABLE
FROM CTE2 C2
JOIN CTE3 C3 ON C2.COUNTRYNAME=C3.COUNTRYNAME AND C2.ITEMNAME=C3.ITEMNAME
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + ITEMNAME + ']', '[' + ITEMNAME + ']')
FROM (SELECT DISTINCT ITEMNAME FROM #NEWTABLE WHERE ITEMNAME<>'TOTAL') PV
ORDER BY ITEMNAME
-- Since we need Total in last column, we append it at last
SELECT #cols += ',[Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT COUNTRYNAME,' + #cols + ' FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,ISNULL(NEWCOL,''0x 0$'')NEWCOL
FROM #NEWTABLE
) x
PIVOT
(
MIN(NEWCOL)
FOR ITEMNAME IN (' + #cols + ')
) p
ORDER BY CASE WHEN (COUNTRYNAME=''Total'') THEN 1 ELSE 0 END,COUNTRYNAME'
EXEC SP_EXECUTESQL #query
and here is result ;
As you can see there are 2 "playstation" from "Russia" it takes correct count (2x) but only take 1 price "151$" (normally it must be 302$). How can I fix this without making major changes from query? Thank you.
I think this does what you want. The problem is in your first CTE where you do the item count and get a distinct on the ItemName, CountryName, and Price.
Instead of getting a distinct, do a group by as shown below and SUM the price.
SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME
,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
GROUP BY
I.NAME
,C.NAME
EDIT:
Here are the results I get:
Here's all of your code starting from the CTEs:
;WITH CTE AS
(
SELECT I.NAME ITEMNAME, C.NAME COUNTRYNAME
,SUM(CAST(REPLACE(TAB.PRICE,'$','')AS INT))PRICE
,COUNT(CASE WHEN TAB.PRICE IS NOT NULL THEN 1 ELSE NULL END) CNTITEM
FROM [#Pre-Request] PR
LEFT JOIN #Items I ON PR.ITEMID=I.ID
LEFT JOIN #COUNTRY C ON PR.COUNTRYID = C.ID
OUTER APPLY
(
SELECT R.preReqId,R.winOfferId,O.PRICE
FROM #Request R
JOIN #Offers O ON R.winOfferId=O.Id
WHERE PR.ID=R.preReqId
)TAB
GROUP BY
I.NAME
,C.NAME
UNION
-- Used to select Item name and country that are not in Pre-request table and other tables
SELECT I.NAME ,C.NAME ,NULL,0
FROM #Items I
CROSS JOIN #COUNTRY C
)
,CTE2 AS
(
-- Find the sum for number of items
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME,
SUM(PRICE)PRICE
FROM CTE
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
,CTE3 AS
(
-- Find the sum of PRICE
SELECT DISTINCT ISNULL(ITEMNAME,'TOTAL')ITEMNAME,ISNULL(COUNTRYNAME,'TOTAL')COUNTRYNAME--,CNTITEM
,SUM(CNTITEM)CNTITEM
FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,CNTITEM
FROM CTE
)TAB
GROUP BY ITEMNAME,COUNTRYNAME
WITH CUBE
)
SELECT C2.*,C3.CNTITEM,
CAST(C3.CNTITEM AS VARCHAR(20))+'x'+' ' + CAST(C2.PRICE AS VARCHAR(20))+'$' NEWCOL
INTO #NEWTABLE
FROM CTE2 C2
JOIN CTE3 C3 ON C2.COUNTRYNAME=C3.COUNTRYNAME AND C2.ITEMNAME=C3.ITEMNAME
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + ITEMNAME + ']', '[' + ITEMNAME + ']')
FROM (SELECT DISTINCT ITEMNAME FROM #NEWTABLE WHERE ITEMNAME<>'TOTAL') PV
ORDER BY ITEMNAME
-- Since we need Total in last column, we append it at last
SELECT #cols += ',[Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT COUNTRYNAME,' + #cols + ' FROM
(
SELECT DISTINCT ITEMNAME,COUNTRYNAME,ISNULL(NEWCOL,''0x 0$'')NEWCOL
FROM #NEWTABLE
) x
PIVOT
(
MIN(NEWCOL)
FOR ITEMNAME IN (' + #cols + ')
) p
ORDER BY CASE WHEN (COUNTRYNAME=''Total'') THEN 1 ELSE 0 END,COUNTRYNAME'
EXEC SP_EXECUTESQL #query

Pivot multiple columns in SQL Server 2008

I am trying to convert column to rows. I am beginner to PIVOT. Tried below code but error is coming as 'Error converting data type nvarchar to datetime.
The incorrect value "Tot_GPS_Cnt" is supplied in the PIVOT operator.'
CREATE TABLE #tbl_Res1
(
CallDate DATETIME,
Tot_GPS_Cnt INT,
Tot_GND_Cnt INT,
Per_Ratio NUMERIC(10,2)
)
INSERT INTO #tbl_Res1
SELECT '2015-04-24 00:00:00.000','40','26','65.00' UNION ALL
SELECT '2015-04-25 00:00:00.000','22','14','63.64' UNION ALL
SELECT'2015-04-26 00:00:00.000','27','21','77.78' UNION ALL
SELECT'2015-04-27 00:00:00.000','41','23','56.10'
Source Table
Desired Output
I have tried with below query bu failing. Please help. Thanks in advance
SELECT CallDate=col, Tot_GPS_Cnt, Tot_GND_Cnt, Per_Ratio
FROM
( select CallDate, col, value from #tbl_Res1
cross apply
(
SELECT 'Tot_GPS_Cnt',cast(Tot_GPS_Cnt as varchar(10)) UNION ALL
SELECT 'Tot_GND_Cnt', cast(Tot_GND_Cnt as varchar(10)) UNION ALL
SELECT 'Per_Ratio', cast(Per_Ratio as varchar(10))
) c (col,value)
) d
PIVOT
(
max(value) for CallDate in ([Tot_GPS_Cnt], [Tot_GND_Cnt], [Per_Ratio])
) as piv
The correct syntax for PIVOT is:
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
Hence, you have to place date values not [Tot_GPS_Cnt], [Tot_GND_Cnt], [Per_Ratio] in place of pivoted columns:
SELECT CallDate=col, [2015-04-24], [2015-04-25], [2015-04-26], [2015-04-27]
FROM
( select CallDate, col, value from #tbl_Res1
cross apply
(
SELECT 'Tot_GPS_Cnt',cast(Tot_GPS_Cnt as varchar(10)) UNION ALL
SELECT 'Tot_GND_Cnt', cast(Tot_GND_Cnt as varchar(10)) UNION ALL
SELECT 'Per_Ratio', cast(Per_Ratio as varchar(10))
) c (col,value)
) d
PIVOT
(
max(value) for CallDate in ([2015-04-24], [2015-04-25], [2015-04-26], [2015-04-27])
) as piv
Thank you #Giorgos Betsos. I just made dynamic solution. Just wanted to share with all.
DECLARE #coldata VARCHAR(500);
DECLARE #sql VARCHAR(MAX);
SELECT #coldata = COALESCE(#coldata + '], [', '') + CONVERT(VARCHAR(10),calldate,110)
FROM #tbl_Res1;
SELECT #coldata = '[' + #coldata +']';
SELECT #coldata;
SET #sql = 'SELECT CallDate=col, ' + #coldata + '
FROM
( SELECT CallDate, col, value FROM #tbl_Res1
cross apply
(
SELECT ''Tot_GPS_Cnt'', CAST(Tot_GPS_Cnt as VARCHAR(10)) UNION ALL
SELECT ''Tot_GND_Cnt'', CAST(Tot_GND_Cnt as VARCHAR(10)) UNION ALL
SELECT ''Per_Ratio'', CAST(Per_Ratio as VARCHAR(10))
) c (col,value)
) d
PIVOT
(
MAX(value) FOR CallDate IN (' + #coldata + ')
) as piv'
SELECT #sql;
EXECUTE (#SQL);

SQL query problem

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
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
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.
Dynamic SQL with a cursor is the only way I can think of, and it won't be pretty.
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