MS SQL:Pivot Table order columns - sql

I'm hoping some can help clarify what I should be doing. I'm essentially reading in a Table with dates and then Im trying to convert these dates into individual columns.
Unfortunately the columns come out out of order. How do I order these columns into |01/01/2013|02/01/2013| etc? Any guidance would be much appreciated.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.GL_Effective_Date)
FROM [03_rdm].[Table_2013] c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Ref_Account_Class, ' + #cols + ' from
(
select TOP 100 PERCENT
Ref_Account_Class
, GL_Amount
, GL_Effective_Date
from [03_rdm].[Table_2013]
where Ref_Account_Class = ''Accounts Receivable''
order by GL_Effective_Date
) x
pivot
(
max(GL_Amount)
for GL_Effective_Date in (' + #cols + ')
) p '
execute(#query)

You need to order in this statement:
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.GL_Effective_Date)
FROM [03_rdm].[Table_2013] c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
When using distinct though, you can only order by items in the select list, so you can't order by c.GL_Effective_Date, it would need to be the full statement (',' + QUOTENAME(c.GL_Effective_Date), but since QUOTENAME implicitly converts your date to a VARCHAR these will not come out in order. So instead of DISTINCT you can use GROUP BY to remove duplicates:
SET #cols = STUFF((SELECT ',' + QUOTENAME(c.GL_Effective_Date)
FROM [03_rdm].[Table_2013] c
GROUP BY c.GL_Effective_Date
ORDER BY c.GL_Effective_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Which should give the ordering you require. This should also be marginally more efficient, although probably not noticably. When you use a scalar function with distinct the function is applied to all rows, then duplicates removed from the results, however with group by, first duplicates are removed, then the function is applied to the results. As mentioned, this will not be noticable with QUOTENAME, but be a useful bit of knowledge to have for future reference.

Instead of using distinct, use group by:
SET #cols = STUFF((SELECT ',' + QUOTENAME(c.GL_Effective_Date)
FROM [03_rdm].[Table_2013] c
GROUP BY c.GL_Effective_Date
ORDER BY c.GL_Effective_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),
1, 1, '');

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

Workaround DECLARE statement in View

I have the following which I would like to be a View, but the Declare statement is not allowed apparently.
What is the best solution/work-around to this problem?
I'm using SQL Server. I have tried many other solutions (Stored Procedures, Table-Values Functions), but I think the combination of Dynamic SQL is complicating the matter and I haven't been able to get anything working.
DECLARE #cols AS NVARCHAR(MAX),
#colsAlias AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(MeasurementTypeID)
FROM dbo.Measurements
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT #colsAlias = STUFF((SELECT DISTINCT ',' + QUOTENAME(dbo.Measurements.MeasurementTypeID) + ' AS ' + QUOTENAME(dbo.MeasurementTypes.MeasurementType)
FROM dbo.Measurements INNER JOIN dbo.MeasurementTypes ON dbo.Measurements.MeasurementTypeID = dbo.MeasurementTypes.MeasurementTypeID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #query = 'SELECT NeuronID, ' + #colsAlias +' FROM
(
SELECT MeasurementName, MeasurementValue, NeuronID, MeasurementTypeID
FROM dbo.Measurements
) x
PIVOT
(
MIN(MeasurementValue) FOR MeasurementTypeID IN (' + #cols + ')
) AS p'
EXECUTE(#query)

How can I get a SQL query result in CSV format?

I have an SQL query that returns some rows. How can I change it so that the output of the query is in CSV format?
I have found a way to make the result in XML format, but because of the nature of XML the result is too large to be useful.
The query is very large (and it's not really important), so I wont post it here. Here is a link to it.Link
I don't want the SQL query to save the result as a CSV file.
YES
try this
DECLARE #query nvarchar(max)
select #query = STUFF( (SELECT N',' + cast( id as nvarchar)
from TableX
--some WHERE clause here as well
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
select #query
NO variable :
select STUFF( (SELECT N',' + cast( id as nvarchar)
from TableX
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
Like this:
select field1
, '","'
, field2
, '","'
etc

SQL PIVOT syntax is wrong

Trying to create a view with a PIVOT in it, can't figure out the syntax. The source view has three columns: ClientNameID, Item, and CountOfItem. I want ClientNameID to be the row, Item to be the column, and CountOfItem to be the value.
I figured it out:
SELECT clientnameid
FROM dbo.vAggregateSalesByCustomerAndItem
pivot (
Sum(countOfItem) FOR Item in ([Ring])
) PivotTable
The problem was syntax BUT I also learned that the dimensions (columns) must be hard-coded in the DML. I wanted to get the dimensions dynamically from a table, which is do-able in Excel, with a column range, but not here.
I think you should try this. its worked for you..
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT DISTINCT ',' + Item
from dbo.vAggregateSalesByCustomerAndItem
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT clientnameid ' + #cols + ' from
(
select clientnameid,countOfItem,Item
from dbo.vAggregateSalesByCustomerAndItem
) x
pivot
(
Sum(countOfItem)
for Item in (' + #cols + ')
) p '
execute(#query);

while converting column to row not able to fetch value from another table automatically

select *
from (
select vtid, convert(date, dtime) as Date from Transaction_tbl where locid = 5
) as vt
pivot (
count(vtid)
for vtid in (select vtid from VType_tbl)
) as pvt
while executing this query am getting error
Incorrect syntax near the keyword 'select'." and Incorrect syntax near
')'.
actually I have one more table,name= Vtype_table , How Can I load all vtid from vtype table in this query? I want to get output depend upon vtid.
Any help greatly appreciated.
Your PIVOT syntax is correct except you are using a SELECT statement inside your PIVOT.
You cannot use a SELECT statement inside the PIVOT IN clause to select column headers. It is required that the columns for the IN clause be known prior to executing the query.
If you are looking to generate a dynamic list of vtid values, then you will need to use dynamic SQL to get the result and the syntax will be similar to the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vtid)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select vtid, convert(date, dtime) as Date
from Transaction_tbl
where locid = 5
) d
pivot
(
count(vtid)
for vtid in (' + #cols + ')
) p '
execute(#query);
Edit, if you want the type names to appear then you should be able to use the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vt_name)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select v.vt_name, convert(date, dtime) as Date
from Transaction_tbl t
inner join VType_tbl v
on t.vtid = v.vtid
where locid = 5
) d
pivot
(
count(vt_name)
for vt_name in (' + #cols + ')
) p '
execute(#query)
Note: I am guessing on the column name for VType_tbl