I'm tring to get multiple results from a dynamic exec to be columns of a table in a single output using SQL Server, right now the exec gives me multiple outputs as different temporal tables.
Is there a way to merge them together and get a single output?
This is my code:
Declare #status nvarchar(255)
Declare POINTER cursor global for select distinct status from intermedio
open POINTER
fetch NEXT from POINTER into #status
while (##FETCH_STATUS=0)
begin
exec('select distinct(
Select COUNT(*) from (
SELECT DISTINCT PKN
FROM INTERMEDIO
WHERE PIECE IN ('+'''+891''','''+75'''+') and ESTATUS = '''+#status+'''
group by PKN
having count(*)=2
) ser) as '+#status);
fetch next from POINTER into #status
end;
close POINTER;
DEALLOCATE POINTER;
Edit: Tried to explain myself better, once again excuse my poor english.
My table has three columns
+-----------+-------+---------+
| PKN | PIECE | ESTATUS |
+-----------+-------+---------+
| Set_one | +891 | A1 |
| Set_one | +75 | A1 |
| Set_one | +45 | A1 |
| Set_two | +891 | A3 |
| Set_two | +75 | A3 |
| Set_three | +700 | B1 |
+-----------+-------+---------+
I'm trying to get the count of the PKNs that have both (+891, +75) and count how many exist under ESTATUS
The output I'm expecting is something like:
+----+----+----+
| A1 | A3 | B1 |
+----+----+----+
| 1 | 1 | 0 |
+----+----+----+
But it gives me the rows on different tables.
The reason I'm doing it like this is because the table can have many different ESTATUS at any time, and many different pieces on different PKN, the result will change constantly and the table generated will be different each time I execute the query.
I'm sorry if the question isn't clear, as english is not my first language.
You are looking for a dynamic pivot and a conditional aggregation. Here's an example.
create table #tempTable (PKN varchar(64), PIECE varchar(64), ESTATUS varchar(2))
insert into #tempTable
values
('Set_one','+891','A1'),
('Set_one','+75','A1'),
('Set_one','+45','A1'),
('Set_two','+891','A3'),
('Set_two','+75','A3'),
('Set_three','+700','B1')
select
ESTATUS
--here is the conditional aggregation
,floor(count(case when PIECE = '+891' or PIECE = '+75' then PKN end)/2) as CT
into #staging
from
#tempTable
group by ESTATUS
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(ESTATUS)
FROM (SELECT DISTINCT ESTATUS FROM #staging) AS ESTATUS
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
N'SELECT ' + #ColumnName + '
FROM #staging
PIVOT(Sum(CT)
FOR ESTATUS IN (' + #ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
drop table #tempTable
drop table #staging
RETURNS
+----+----+----+
| A1 | A3 | B1 |
+----+----+----+
| 1 | 1 | 0 |
+----+----+----+
Related
I've seen just about every kind of pivot example on the Internet, both text based tutorial and video. Not one is solving the issue at hand.
What I want is to pivot the following table:
Sales Table
SalesId | SalesDate | SalesLocation | SalesAmount
-----------------------------------------------------
1 | 2012-03 | New York, NY | 3,000
2 | 2012-04 | Miami, FL | 2,500
3 | 2012-05 | Carmel, CA | 2,850
4 | 2012-06 | Berkeley, CA | 1,900
5 | 2012-07 | Akron, OH | 4,200
6 | 2012-08 | Portland, OR | 2,200
I would like to PIVOT this table to show each row as a column, not distinct SUM of columns. Each row is specifically it's own column, with the date as the header, as if the table has been turned 90 degrees clockwise like an Excel spreadsheet, for date forecasting:
Account Info | 2012-03 | 2012-04 | 2012-05 | 2012-06
---------------------------------------------------------------------
SalesId | 1 | 2 | 3 | 4
SalesLocation | New York, NY | Miami, FL | Carmel, CA | Berkeley, CA
SalesAmount | 3,000 | 2,500 | 2,850 | 1,900
Most of the tutorials on this subject involve creating sums of several rows that have either the same city, the same status or the same type.
For this situation, each row already has a distinct unique date that will never be duplicated, so all records are unique and therefore do not require a function like SUM.
So far, after viewing an incredibly clear solution by JoyceW on the PIVOT Using Date Column thread at the ASP.net forums, I have gotten this far:
declare #cols varchar(max)
select #cols = (select distinct SalesDate from SalesTable for xml path(''))
select #cols = replace(#cols, '', '[')
select #cols = replace(#cols, '', '],')
select #cols = left(#cols, len(#cols) - 1)
declare #query varchar(max)
select #query = 'select * from (select SalesId, SalesLocation, SalesAmount
from SalesTable) src pivot (max(SalesAmount) for SalesDate in ('
+ #cols + ')) piv;'
execute(#query)
While this is not what I was looking for, it's the only tutorial that has allowed me to actually return a result set where the top columns are actually the dates (yay), as seen below:
SalesId | SalesLocation | SalesAmount | 2012-03 | 2012-04 | 2012-05
1 | New York, NY | 3,000 | {null} | {null} | 4
2 | Miami, FL | 2,500 | {null} | 3 | {null}
3 | Carmel, CA | 2,850 | {null} | {null} | {null}
4 | Berkeley, CA | 1,900 | 1 | {null} | {null}
5 | Akron, OH | 4,200 | {null} | {null} | {null}
6 | Portland, OR | 2,200 | {null} | 2 | {null}
Not really sure what's going on here, but it's a lot closer than I was before, I'm actually receiving a result set. Any ideas about how to fine tune this where the rows showing up need to be rotated or pivoted as well?
It seems that I'm only pivoting the headers and not the entire table as I would like. Any suggestions would be greatly appreciated.
As you want multiple aggregation columns in your pivot you have to do the iterations for each aggregation value. I am using Sales as the table name. Please change the table name if it is different for you. Below query should give you the result you want.
DECLARE #cols AS NVARCHAR(MAX),
#Convertcols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#SQL AS NVARCHAR(MAX),
#PivotColumn Varchar(100),
#i Int = 1,
#AggColumn Varchar(100)
DECLARE #Columns TABLE (ID int IDENTITY(1,1), AccountInfo Varchar(max))
SELECT #cols = STUFF((SELECT ', '+ QUOTENAME(SalesDate)
from Sales
group by SalesDate
order by SalesDate
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #Convertcols = STUFF((SELECT ', CAST( '+ QUOTENAME(SalesDate) + ' AS VARCHAR(max)) AS ' + QUOTENAME(SalesDate)
from Sales
group by SalesDate
order by SalesDate
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
INSERT INTO #Columns
SELECT C.name
FROM SYS.COLUMNS C
INNER JOIN SYS.TABLES T ON C.OBJECT_ID = T.OBJECT_ID
WHERE T.NAME = 'Sales'
AND C.name <> 'SalesDate'
While #i <= (SELECT MAX(ID) FROM #Columns)
BEGIN
SELECT #AggColumn = AccountInfo FROM #Columns Where ID = #i
set #query = 'SELECT AccountInfo,' + #Convertcols +
' FROM
(
SELECT ''' + #AggColumn + ''' AS AccountInfo, SalesDate, '+ #AggColumn +'
FROM Sales
) X
PIVOT
(
Max('+ #AggColumn +')
FOR SalesDate in (' + #cols + ')
) P '
SET #SQL = CONCAT(#SQL, CHAR(10), CASE WHEN #i = 1 THEN '' ELSE 'UNION ' END, CHAR(10) , #query)
SET #i = #i+1
END
EXECUTE (#SQL)
Result:
In order for you to be able to PIVOT, you'll need to have at least one non-pivoted column - something which your model is lacking.
Documentation: https://technet.microsoft.com/en-us/library/ms177410%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396
I have a large file that has the following fields:
Table 1:
+---------+--------+-----------+
| User_Id | Key_Id | Value |
+---------+--------+-----------+
| 100 | 74 | 37 |
| 100 | 65 | Male |
| 100 | 279 | G235467 |
+---------+--------+-----------+
and I have another file that tells what each 'Key_Id' is called (they are column names) e.g.
Table 2:
+--------+------------------+
| Key_Id | Key |
+--------+------------------+
| 65 | Gender |
| 66 | Height |
| 74 | Age |
| 279 | ReferenceNo |
I want to create a table using the Key_Id names found in the Key column of table 2, transpose all of the values from table 1 into table 2, but also include the User_Id from table 1 as this relates to an individual.
PS. Table 2 has nearly 300 keys that would need turning into individual fields
So ultimately I would like a table that looks like this:
+---------+---------+--------+-------+--------------+--------+
| User_Id | Gender | Height | Age | ReferenceNo | etc |
+---------+---------+--------+-------+--------------+--------+
| 100 | Male | | 37 | G235467 | |
So that each User_Id is a row and that all the Keys are columns with their respective values
You can use a dynamic sql query as below.
Query
declare #sql as varchar(max);
select #sql = 'select t1.[User_Id], ' + stuff((select +
', max(case t2.[Key_Id] when ' + cast([Key_Id] as varchar(100)) +
' then t1.[Value] end) as [' + [Key] + '] '
from Table2
for xml path('')
), 1, 2, '') +
'from Table1 t1 left join Table2 t2 on t1.[Key_Id] = t2.[Key_Id] group by t1.[User_Id];'
exec(#sql);
Find a demo here
You need to get a coma-separated list of those 300 key names to be used in PIVOT/UNPIVOT operators in T-SQL like described here
https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot
you can use pivot as below:
Select * from (
Select u.UserId, k.[key], u.[Value] from table1 u
join table2 k on u.keyid = k.keyid ) a
pivot ( max([Value]) for [key] in ([Gender], [Height], [Age], [ReferenceNo]) ) p
For dynamic list of keys you can use dynamic sql as below:
Declare #cols1 varchar(max)
Declare #query nvarchar(max)
Select #cols1 = stuff((select ','+QuoteName([Key]) from table2 group by [Key] for xml path('')),1,1,'')
Set #Query = 'Select * from (
Select u.UserId, k.[key], u.[Value] from table1 u
join table2 k on u.keyid = k.keyid ) a
pivot ( max([Value]) for [key] in (' + #cols1 + ') ) p '
Select #Query --Check the generated query and execute by uncommenting below query
--exec sp_executesql #Query
I'm having a rough go trying to pivot my data :( It is dynamic data and structured like this:
| Date | Source | Amount |
--------------------------------------------
| 12/1/2016 | Source1 | $0 |
| 12/1/2016 | Source2 | $2 |
| 12/1/2016 | Source3 | $5 |
| 12/1/2016 | Source4 | $4 |
There can be unlimited sources and I want to pivot it by source/date:
| Date | Source1 | Source 2 | Source 3 | Source 4 |
--------------------------------------------------------------------------------------
| 12/1/2016 | $0 | $2 | $5 | $4 |
Something like that, anyway.
I have tried coding a lot of ways, so I'll just put in what I thought it could be:
SELECT myDate , Source, Amount
FROM mydb
PIVOT
(max(source) FOR source IN (select distinct source from mydb) as myPivotTable
WHERE (myDate > #StartDate)
of course, that doesn't work. This was going to be part of a stored procedure, just not quite there. Was hoping to pivot on that data so I can do some line trends in SSRS.
I also followed another example and tried this:
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(source)
from mydb where myDate > #StartDate
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
And then tried to use that in the place of the "select distinct". However, the sources are text and that didn't seem to do much for me.
Here is a simple Dynamic Pivot on Source
Declare #SQL varchar(max) = Stuff((Select Distinct ',' + QuoteName([Source]) From Yourtable Order by 1 For XML Path('')),1,1,'')
Select #SQL = '
Select [Date],' + #SQL + '
From YourTable
Pivot (sum(Amount) For [Source] in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Date Source1 Source2 Source3 Source4
2016-12-01 0 2 5 4
Now, If you want Source to be sequenced Like Source 1, Source 2 it would require just a minor tweak
FYI the generated SQL would look like this
Select [Date],[Source1],[Source2],[Source3],[Source4]
From YourTable
Pivot (sum(Amount) For [Source] in ([Source1],[Source2],[Source3],[Source4]) ) p
I'm trying to create a query in which I use pivot to transform row values into columns. That I am able to do fine. But the requirement is to also use the other columns as row values.
The table and query I have tried can be checked here.
The required output is here.
From the query, I need the values of 'C' to be columns then the other columns (A, B, D & E) to be row values for the first column.
Is it possible to use one single pivot query to display the required output? If not, what would be the best approach to the problem?
SQL Fiddle
MS SQL Server 2008 Schema Setup:
CREATE TABLE Table1
(
A varchar(10),
B varchar(10),
C int,
D varchar(10),
E varchar(10)
)
GO
INSERT INTO Table1 VALUES('A1', 'B1', 1, 'D1', 'E1');
INSERT INTO Table1 VALUES('A2', 'B2', 2, 'D2', 'E2');
INSERT INTO Table1 VALUES('A3', 'B3', 3, 'D3', 'E3');
Query 1:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(C)
from Table1
group by C
order by C
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N';WITH CTE AS
(SELECT *
FROM Table1 UNPIVOT (Vals FOR COLUMNNAMES IN (A,B,D,E))up
)
SELECT *
FROM CTE
PIVOT (MAX(Vals)
FOR C
IN(' + #cols + N'))p '
exec sp_executesql #query
Results:
| COLUMNNAMES | 1 | 2 | 3 |
|-------------|----|----|----|
| A | A1 | A2 | A3 |
| B | B1 | B2 | B3 |
| D | D1 | D2 | D3 |
| E | E1 | E2 | E3 |
I'm hoping someone can help me. I'm trying to pivot some data on SQL Server 2005 and can't quite get the results I'm looking for.
This is my current table schema:
| ProductCode | AttributeName | AttributeValue |
| 1 | AttributeA | 10 |
| 1 | AttributeB | 20 |
| 2 | AttributeA | 30 |
| 2 | AttributeB | 40 |
| 3 | AttributeA | 50 |
This is the results I'm trying to achieve:
| ProductCode | AttributeA | AttributeB |
| 1 | 10 | 20 |
| 2 | 30 | 40 |
| 3 | 50 | NULL |
I know that I can achieve this result with the following SQL:
SELECT DISTINCT ProductCode,
(SELECT AttributeValue
FROM attributes
WHERE ProductName = 'AttributeA' AND ProductCode=a.ProductCode) AttributeA,
(SELECT AttributeValue
FROM attributes
WHERE ProductName = 'AttributeB' AND ProductCode=a.ProductCode) AttributeB,
FROM attributes a
Although that SQL does produce the result I'm looking for, it's obviously not dynamic (in reality, I not only have more Attribute Types, but different products have different sets of attributes) and it also scans the table 3 times. It's also a maintenance nightmare.
I tried using the PIVOT functionality of SQL Server, but with no luck.
Can anyone help?
create table #attributes (ProductCode int,
AttributeName varchar(20),
AttributeValue int)
insert into #attributes values (1, 'AttributeA', 10)
insert into #attributes values (1, 'AttributeB', 20)
insert into #attributes values (2, 'AttributeA', 30)
insert into #attributes values (2, 'AttributeB', 40)
insert into #attributes values (3, 'AttributeA', 50)
declare #attributes_columns nvarchar(max)
set #attributes_columns
= (
select ', [' + AttributeName + ']'
from
(
select distinct AttributeName as AttributeName
from #attributes
) t
order by t.AttributeName
for xml path('')
)
set #attributes_columns = stuff(#attributes_columns,1,2,'')
declare #sql nvarchar(max)
set #sql = N'
select ProductCode, <attributes_columns>
from
(select ProductCode, AttributeName, AttributeValue
from #attributes )p
pivot
(
sum(AttributeValue) for AttributeName in (<attributes_columns>)
) as pvt
'
set #sql = replace(#sql, '<attributes_columns>', #attributes_columns)
print #sql
exec sp_executesql #sql
drop table #attributes