How to to select two columns (Name, Value) and return as single result? - sql

So I have a table that has a column for Name, and a column for Value and an ID. There can be multiple rows for the same ID. I would like to create a select that will return a single row for each ID and the values in the Name column would be the column name, and the Value would be the value. Example:
CREATE TABLE dbo.Attribute
(
AttributeID int NOT NULL,
Name varchar(20) NOT NULL,
Value varchar(20) NOT NULL
) ;
Data:
{1,"Color", "Blue"},{1,"Material", "leather"}
Would like Select to return:
[AttributeID:1, Color:Blue, Material: leather]
I have been playing with PIVOT and UNPIVOT but not getting what I need.

Thanks to #Mihai's link. I was able to do what I
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Name)
FROM VariantAttribute c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT variantid, ' + #cols + ' from
(
select variantid
, Name
, value
from VariantAttribute
) x
pivot
(
max([Value])
for Name in (' + #cols + ')
) p '
execute(#query)
Before I get more slack about how I am storing this data. There is not a way out of it at the moment, but this query is to push this data to Azure Search (uses Elastic search) to be able to easily search on this data.

Related

The type of column "Date" conflicts with the type of other columns specified in the UNPIVOT list

I have the following code to do Pivot and Unpivot on a set of columns:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsUnpivot AS NVARCHAR(MAX)
select #colsUnpivot = stuff((select ','+quotename(C.name)
from tempdb.sys.columns as C
where C.object_id = object_id('tempdb..#TmpTable')
for xml path('')), 1, 1, '')
SET #cols = STUFF((SELECT ',' + QUOTENAME(a.Date)
FROM
(Select top 10000 date from
#TmpTable
order by date) a
group by a.Date
order by a.Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT name, ' + #cols + ' from
(
select Date,name,value
from #TmpTable
unpivot
(
value for name in ('+#colsUnpivot+')
) unpiv
) x
pivot
(
sum(value)
for date in (' + #cols + ')
) p '
exec(#query)
But, I keep getting these errors which I can't figure out why:
The type of column "Date" conflicts with the type of other columns specified in the UNPIVOT list.
Invalid column name 'Date'
The type of Date column in the temp table is datetime.
This post was very helpful to explain the issue. Basically, I had to convert the values to decimal for all the columns in the inner select statement of the unpivot section:
Error : The type of column "DOB" conflicts with the type of other columns specified in the UNPIVOT list

trying to average column with CAST in PIVOT table- Incorrect syntax near '('

I am trying the Pivot function to get the following table-
split rows of TagID into columns, the TagValue of each TagID and DATEADD TimeStamp to display avg values every 5 minutes:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(TagID)
from table
group by TagID
order by TagID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Top (500) DATEADD(minute,DATEDIFF(minute,0,TimeStamp)/5*5,0) AS TimeStamp, ' + #cols + ' from
(
select TimeStamp, TagID , TagValue
from table
Group By TimeStamp, TagID, TagValue
) x
pivot
(
AVG(CAST(TagValue) AS DECIMAL(18,2))
for TagID in ( ' + #cols + ' )
) p '
execute(#query)
I am trying to create avg for the column TagValue.
After I used the CAST function as you can see above, the query displayed:
Msg 102, Level 15, State 1, Line 12
Incorrect syntax near '('.
although I cannot find what is wrong and which exact syntax is incorrect.
Would really appreciate some help here as Management studio doesn't show where the problem is.
I looked up online and normally the avg function is used like this:
AVG(TagValue) although it doesn't work on NVARCHAR column.
There was syntax issue with the CAST statement, also minor changes were made to sub query table x - please try the below code
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(TagID)
FROM table
GROUP BY TagID
ORDER BY TagID
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
SET #query = 'SELECT TOP (500) DATEADD(minute,DATEDIFF(minute,0,TimeStamp)/5*5,0) AS TimeStamp, ' + #cols + ' from
(
select TimeStamp, TagID , TRY_CAST(TagValue AS DECIMAL(18,2)) AS [TagValue]
from table
Group By TimeStamp, TagID, TagValue
) x
pivot
(
AVG(TagValue)
for TagID in ( ' + #cols + ' )
) p '
EXEC(#query)
Change it to AVG(CAST(TagValue AS DECIMAL(18,2))) instead of
AVG(CAST(TagValue) AS DECIMAL(18,2)) in the pivot block.
i.e, you are using CAST(TagValue) AS DECIMAL(18,2)), but it should be CAST(TagValue AS DECIMAL(18,2))
You have issue with CAST Syntax. Use as below-
AVG(CAST(TagValue AS DECIMAL(18,2)))
You query shows table name is 'table'. Can you use the table name second bracket around as below-
FROM [table]

SQL Server: case/if else -select and apply function only if present in table

I have the following dynamic query that creates a pivoted table for each account_id against the products using an UDF. I need to add spaces after the UDF is executed depending up the account_id being matched to the specific tables. This works perfectly fine, and returns the 2nd table in the image, I just want to add some condition where it checks for account id's present in other tables and then adds spaces to output from the UDF eg- the account id in the pivot matches the id present in test_rev then 2 spaces if the account_id in the pivot matches the id present in test_oncontract then 3 spaces so on
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.A_NAME)
FROM TEST_11 c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT account_id, ' + #cols + ' INTO TEST_DETAIL from
(
select account_id
, dbo.make_table(apple,ball,cat,dog) AS newvalue
,a_name
from test_sample
) x
pivot
(
MAX(newvalue)
for a_name in (' + #cols + ')
) p '
execute(#query)
Image below shows how make_table udf converts the 1st table into 2nd just picking up the initials from each column name from the 1st table
I was able to call my function and add the required spaces withing the select.
But the case statement just executes the first condition and I cant get the records from the other tables. How can I implement if conditions instead of the case statements to to get data depending on all four conditions. Below is the code I am currently using:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.a_name)
FROM CRS_PRODLINE c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT account_id, ' + #cols + ' INTO TEST_DETAIL from
(select account_id,
(case
when exists (select account_id from [dbo].[TEST_R6])
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(1) + ''rr''
when exists (select account_id from tbl_noR6)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(2) + ''cc''
when exists (select account_id from tbl_acct)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(3) + ''pp''
when exists (select account_id from test_NA)
then
dbo.make_sam_indicator112(apple,ball,cat,dog) + space(4) + ''no''
end) as newvalue,
a_name
from CRS_PRODLINE
) x
pivot
(
MAX(newvalue)
for a_name in (' + #cols + ')
) p '
execute(#query)

SQL query unknown rows into columns

I asked this question and it was marked as a duplicate of How to pivot unknown number of columns & no aggregate in SQL Server?, but that answer doesn't help me.
I have a table of data that looks like this, with an unknown number of rows and values.
RecID Name Value
1 Color Red
2 Size Small
3 Weight 20lbs
4 Shape Square
I need a query that will return the data like this, building out a column for each row. I cannot hard code anything except the column headers 'Name' and 'Value'.
Color Size Weight Shape
Red Small 20lbs Square
Here is what I have so far that is partly working:
INSERT INTO #Table VALUES
(1,'Color' ,'Red'),
(2,'Size' ,'Small'),
(3,'Weight','20lbs'),
(4,'Shape' ,'Square')
;with mycte
as
(
SELECT rn,cols,val
FROM (SELECT row_number() over(order by Name) rn, Name, Value
FROM #Table) AS src1
UNPIVOT (val FOR cols
IN ( [Name], [Value])) AS unpvt
)
SELECT *
FROM (SELECT rn,cols,val
FROM mycte) AS src2 PIVOT
( Max(val) FOR rn IN ([1], [2], [3])) AS pvt
Which returns:
cols 1 2 3
Name Color Shape Size
Value Red Square Small
Two problems with this that I can't seem to resolve.
I don't need the column headers and the first column that has cols, Name, Value in it.
Can't figure out how to have it build a column for each row without specifying the [x] identifiers.
Any guidance would be great I've been stuck on this a while now.
declare #collist nvarchar(max)
SET #collist = stuff((select distinct ',' + QUOTENAME(name)
FROM #t -- your table here
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #q nvarchar(max)
set #q = '
select *
from (
select rn, name, Value
from (
select *, row_number() over (partition by name order by RecID desc) as rn
from #t -- your table here
) as x
) as source
pivot (
max(Value)
for name in (' + #collist + ')
) as pvt
'
exec (#q)
Until now, I have reached to following code, hope it helps you,
Current outpu comes as
Color Shape Size Weight
Red NULL NULL NULL
NULL NULL Small NULL
NULL NULL NULL 20lbs
NULL Square NULL NULL
Create table DyTable
(
tid int,
Name varchar(20),
Value varchar(20)
)
INSERT INTO DyTable VALUES
(1,'Color' ,'Red'),
(2,'Size' ,'Small'),
(3,'Weight','20lbs'),
(4,'Shape' ,'Square')
DECLARE #Cols NVARCHAR(MAX);
DECLARE #Cols1 NVARCHAR(MAX);
SELECT #Cols = STUFF((
SELECT DISTINCT ', ' + QUOTENAME(Name)
FROM DyTable
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
,#Cols1 = STUFF((
SELECT DISTINCT ', max(' + QUOTENAME(Name) + ') as ' + Name
FROM DyTable
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,'')
DECLARE #Sql NVARCHAR(MAX)
Select #Cols
SET #Sql = 'Select '+ #Cols1 +'
from (SELECT ' + #Cols + '
FROM DyTable t
PIVOT (MAX(Value)
FOR Name
IN (' + #Cols + ')
)P)a'
EXECUTE sp_executesql #Sql

Dynamic pivot table with multiple columns in sql server

I am trying to pivot table DYNAMICALLY but couldn't get the desired result.
Here is the code to create a table
create table Report
(
deck char(3),
Jib_in float,
rev int,
rev_insight int,
jib_out float,
creation int
)
insert into Report values
('A_1',0.345,0,0,1.23,20140212),
('B_2',0.456,0,4,2.34,20140215),
('C_3',0.554,0,6,0.45,20140217),
('D_4',0.231,0,8,7.98,20140222),
('E_5',0.453,0,0,5.67,20140219),
('F_6',0.344,0,3,7.23,20140223)'
Code written so far.... this pivots the column deck and jib_in into rows but thats it only TWO ROWS i.e the one i put inside aggregate function under PIVOT function and one i put inside QUOTENAME()
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(deck)
FROM (SELECT p.deck FROM dbo.report AS p
GROUP BY p.deck) AS x;
SET #sql = N'
SELECT ' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT p.deck, p.jib_in
FROM dbo.report AS p
) AS j
PIVOT
(
SUM(jib_in) FOR deck IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
PRINT #sql;
EXEC sp_executesql #sql;
I need all the columns to be pivoted and show on the pivoted table. any help would be appreciated. I am very new at dynamic pivot. I tried so many ways to add other columns but no avail!!
I know there are other ways please feel free to mention if there is any other way to get this right.
Please use this (If you are getting Collation issue, please change all the 3 INT datatypes):
STATIC code:
SELECT HEADER, [A_1],[B_2],[C_3],[D_4],[E_5],[F_6]
FROM
(SELECT DECK,HEADER, VALUE FROM REPORT
UNPIVOT
(
VALUE FOR HEADER IN ([JIB_IN],[REV],[REV_INSIGHT],[JIB_OUT],[CREATION])
) UNPIV
) SRC
PIVOT
(
SUM(VALUE)
FOR DECK IN ([A_1],[B_2],[C_3],[D_4],[E_5],[F_6])
) PIV
Using Dynamic SQL:
DECLARE #COLSUNPIVOT AS NVARCHAR(MAX),
#QUERY AS NVARCHAR(MAX),
#COLSPIVOT AS NVARCHAR(MAX)
SELECT #COLSUNPIVOT = STUFF((SELECT ','+QUOTENAME(C.NAME)
FROM SYS.COLUMNS AS C
WHERE C.OBJECT_ID = OBJECT_ID('REPORT') AND C.NAME <> 'DECK'
FOR XML PATH('')), 1, 1, '')
SELECT #COLSPIVOT = STUFF((SELECT ',' + QUOTENAME(DECK)
FROM REPORT T FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
SET #QUERY
= 'SELECT HEADER, '+#COLSPIVOT+'
FROM
(
SELECT DECK,HEADER,VALUE FROM REPORT
UNPIVOT
(
VALUE FOR HEADER IN ('+#COLSUNPIVOT+')
) UNPIV
) SRC
PIVOT
(
SUM(VALUE)
FOR DECK IN ('+#COLSPIVOT+')
) PIV'
EXEC(#QUERY)