Splicing SQL display Chinese characters problem - sql

I have following SQL script which I hope to cross apply to select Chinese column name
CREATE TABLE #temp([color] varchar(5), [size] varchar(5),[AQty] varchar(10),[BQty] varchar(10),[CQty] varchar(10),[DQty] varchar(10));
INSERT INTO #temp([color], [size], [AQty], [BQty],[CQty],[DQty])
VALUES ('A1', 'L','1','2','3','4')
, ('A1', 'M','1','2','3','4')
, ('A1', 'S','1','2','3','4')
, ('A1', 'XL','1','2','3','4')
, ('B1', 'L','1','2','3','4')
, ('B1', 'M','1','2','3','4')
, ('B1', 'S','1','2','3','4')
, ('B1', 'XL','1','2','3','4')
, ('B1', 'XXL','1','2','3','4')
, ('C1', 'L','1','2','3','4')
, ('C1', 'S','1','2','3','4')
declare #cols as varchar(max), #sql varchar(max)
select #cols = STRING_AGG(col, ', ') from (
select distinct QUOTENAME(size) as col from #temp
) as t
set #sql = '
select color, col as total, ' + #cols + '
from(
select color, size, col, [value]
from #temp
cross apply (
select ''总数一'', cast(AQty as varchar(10)) union all
select ''总数二'', cast(BQty as varchar(10)) union all
select ''总数三'', cast(CQty as varchar(10)) union all
select ''总数四'', cast(DQty as varchar(10))
) c(col, [value])
) d
pivot
(
max(value)
for size in (' + #cols + ')
) piv
order by color, total
'
exec(#sql)
But now exec SQL is display garbled when I hope to display Chinese column name
color total L M S XL XXL
A1 ??? 4 4 4 4 NULL
B1 ??? 4 4 4 4 4
C1 ??? 4 NULL4 NULLNULL
I tried to change it like this, change variable nvarchar, set #sql with N and change cross apply select with N, but now not work.
declare #cols as nvarchar(max), #sql nvarchar(max)
set #sql = N'
select color, col as total, ' + #cols + '
from(
select color, size, col, [value]
from #temp
cross apply (
select N''总数一'', cast(AQty as varchar(10)) union all
select N''总数二'', cast(BQty as varchar(10)) union all
select N''总数三'', cast(CQty as varchar(10)) union all
select N''总数四'', cast(DQty as varchar(10))
) c(col, [value])
) d
pivot
(
max(value)
for size in (' + #cols + ')
) piv
order by color, total
'
exec(#sql)

I have solved my problem by adding N after + #cols +
declare #cols as nvarchar(max), #sql nvarchar(max)
set #sql = N'
select color, col as total, ' + #cols + N'
from(
select color, size, col, [value]
from #temp
cross apply (
select N''总数一'', cast(AQty as varchar(10)) union all
select N''总数二'', cast(BQty as varchar(10)) union all
select N''总数三'', cast(CQty as varchar(10)) union all
select N''总数四'', cast(DQty as varchar(10))
) c(col, [value])
) d
pivot
(
max(value)
for size in (' + #cols + ')
) piv
order by color, total
'
exec(#sql)

Related

Interchange row and column

I have shared sample query and expected result. My queried result is like
Query for this
select *
into #res
from (
select 'B1' branch,123 amount,2 count,1234 Total
union all
select 'B2' branch,523 amount,23 count,123 Total
union all
select 'B3' branch,666 amount,9 count,652 Total
union all
select 'B4' branch,234 amount,12 count,256 Total
) res
select * from #res
Expected Result Image
I tried using pivot but I didn't get.
if only your branch is dynamic, you can union the amount, count and total.
select * into #res from (
select 'B1' branch,123 amount,2 count,1234 Total
union all
select 'B2' branch,523 amount,23 count,123 Total
union all
select 'B3' branch,666 amount,9 count,652 Total
union all
select 'B4' branch,234 amount,12 count,256 Total
union all
select 'B5' branch,233 amount,12 count,256 Total
)res
declare #cols nvarchar(max);
declare #sql nvarchar(max);
select #cols =
stuff((select N'],[' + branch
from (select branch
from #res) AS t1
for xml path('')
), 1, 2, '') + N']';
set #sql = N'Select ''desc'' as [desc], ' + #cols + N'
from (select branch from #res)t1
pivot
(
max(t1.branch)
for t1.branch in (' + #cols + N')
) p
union all
Select ''amount'' as [desc], ' + #cols + N'
from (select cast(amount as varchar(30)) as amount, branch from #res)t1
pivot
(
max(t1.amount)
for t1.branch in (' + #cols + N')
) p
union all
Select ''count'' , ' + #cols + N'
from (select cast([count] as varchar(30)) as [count], branch from #res)t1
pivot
(
max(t1.[count])
for t1.branch in (' + #cols + N')
) p
union all
Select ''Total'' , ' + #cols + N'
from (select cast([Total] as varchar(30)) as [Total], branch from #res)t1
pivot
(
max(t1.[Total])
for t1.branch in (' + #cols + N')
) p
'
print #sql;
exec sp_executesql #sql;
drop table #res

How to convert row data to column in sql server

I have a table Test with 2 column Job_name and Status contains below data,
Job_Name status
------------------------
a failed
b completed
c waiting
d failed
I want output like below,
col1 col2 col3 col4
--------------------------------------
a b c d
failed completed waiting failed
I tried using pivot , but not able to achieve the exact output .
Please let me know , how can I proceed with this.
Thanks in advance.
Try this:
declare #x table (Job_Name char(1), [status] varchar(15))
insert into #x values
('a','failed'),
('b','completed'),
('c','waiting'),
('d','failed')
select * from
(
select 'col' + CAST(ROW_NUMBER() over (order by job_name) as varchar(2)) [colName],
[status]
from #x
) as [toPivot]
pivot
(
max([status])
for
colName in([col1],[col2],[col3],[col4])
) as [p1]
union all
select * from
(
select 'col' + CAST(ROW_NUMBER() over (order by job_name) as varchar(2)) [colName],
Job_Name
from #x
) as [toPivot]
pivot
(
max([job_name])
for
colName in([col1],[col2],[col3],[col4])
) as [p2]
Using a Dynamic Pivot
SET NOCOUNT ON
IF OBJECT_ID ('tempdb..##Tmp') IS NOT NULL DROP TABLE ##Tmp
DECLARE #sql NVARCHAR(MAX)
DECLARE #cols nvarchar(max) = ''
DECLARE #hdrs nvarchar(max) = ''
DECLARE #Cols1 nvarchar(max) = ''
; WITH T (JOb_Name , Status) as
(
SELECT 'a' ,'failed'
UNION ALL
SELECT 'b' ,'completed'
UNION ALL
SELECT 'c' ,'waiting'
UNION ALL
SELECT 'd' , 'failed'
)
SELECT *
INTO ##Tmp
FROM t
SELECT #hdrs += ','+QUOTENAME(JOb_Name) + ' AS Col_'+ CAST(ROW_NUMBER () OVER(ORDER BY job_Name) AS nvarchar(5))
FROM ##Tmp
ORDER BY JOb_Name
SET #hdrs = STUFF(#hdrs,1,1,'')
SELECT #cols += ','+QUOTENAME(JOb_Name)
FROM ##Tmp
ORDER BY JOb_Name
SET #cols = STUFF(#Cols ,1,1,'')
SELECT #Cols1 += ','+QUOTENAME(Cols)
FROM
(
SELECT Job_Name, 'Col_' + CAST(ROW_NUMBER () OVER(ORDER BY job_Name) AS nvarchar(5)) Cols
FROM ##Tmp
) X
SET #Cols1 = STUFF (#cols1,1,1,'')
SET #sql =
'
SELECT *
FROM
(
SELECT Job_Name, ''Col_'' + CAST(ROW_NUMBER () OVER(ORDER BY job_Name) AS nvarchar(5)) Cols
FROM ##Tmp
) x
PIVOT (
MAX(Job_Name) FOR Cols IN ('+#cols1+')
) P
UNION ALL
SELECT '+#hdrs+'
FROM ##Tmp
PIVOT (
MAX(Status) FOR Job_Name IN ('+#cols+')
) P
'
exec sp_executesql #sql
DROP TABLE ##Tmp

Row and column total in dynamic pivot with multiple Select column

In SQL Server 2008, I have a table tblStock with 4 columns:
PartCode (NVARCHAR (50))
Role (NVarchar(10))
StockQty (INT)
Location (NVARCHAR(50))
Some example data below:
I have written this code to get the following output:
IF OBJECT_ID('tempdb..#tblData') IS NOT NULL
DROP TABLE #tblData
SELECT *
INTO #tblData
FROM
(SELECT 'A' PartCode, 'Manager' As [Role], 10 StockQty, 'in-A' Location
UNION ALL
SELECT 'B', 'Director' As [Role], 22, 'in-A'
UNION ALL
SELECT 'A', 'Director' As [Role], 1, 'in-B'
UNION ALL
SELECT 'C', 'Director' As [Role], 20, 'in-A'
UNION ALL
SELECT 'D', 'Director' As [Role], 39, 'in-F'
UNION ALL
SELECT 'E', 'Director' As [Role], 3, 'in-D'
UNION ALL
SELECT 'F', 'Director' As [Role], 7, 'in-A'
UNION ALL
SELECT 'A', 'Director' As [Role], 9, 'in-C'
UNION ALL
SELECT 'D', 'Director' As [Role], 2, 'in-A'
UNION ALL
SELECT 'F', 'Director' As [Role], 54, 'in-E') TAB
SELECT *
FROM #tblData
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + Location + ']', '[' + Location + ']')
FROM (SELECT DISTINCT Location FROM #tblData) PV
ORDER BY Location
SELECT #cols += ',[Total]'
DECLARE #NulltoZeroCols NVARCHAR (MAX)
SELECT #NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+Location+'],0) AS ['+Location+']'
FROM (SELECT DISTINCT Location FROM #tblData)TAB
ORDER BY Location FOR XML PATH('')),2,8000)
SELECT #NullToZeroCols += ',ISNULL([Total],0) AS [Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT PartCode, Role, ' + #NulltoZeroCols + ' FROM
(
SELECT
ISNULL(CAST(PartCode AS VARCHAR(30)),''Total'')PartCode,
Role,
SUM(StockQty)StockQty ,
ISNULL(Location,''Total'')Location
FROM #tblData
GROUP BY Location,PartCode,Role
WITH CUBE
) x
PIVOT
(
MIN(StockQty)
FOR Location IN (' + #cols + ')
) p
ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode'
EXEC SP_EXECUTESQL #query
Result for the above query is:
I want to get the result like this:
Please share your ideas - thanks!
Not MIN, use SUM. Also, you should not select the Role column.
Try this;
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + Location + ']', '[' + Location + ']')
FROM (SELECT DISTINCT Location FROM #tblData) PV
ORDER BY Location
SELECT #cols += ',[Total]'
DECLARE #NulltoZeroCols NVARCHAR (MAX)
SELECT #NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+Location+'],0) AS ['+Location+']'
FROM (SELECT DISTINCT Location FROM #tblData)TAB
ORDER BY Location FOR XML PATH('')),2,8000)
DECLARE #SumCols NVARCHAR (MAX)
SELECT #SumCols = SUBSTRING((SELECT '+(ISNULL(['+Location+'],0))'
FROM (SELECT DISTINCT Location FROM #tblData)TAB
ORDER BY Location FOR XML PATH('')),2,8000)
PRINT #SumCols
SET #SumCols += ') AS [Total]'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT PartCode, (SELECT TOP 1 Role FROM #tblData WHERE PartCode=p.PartCode) Role, ' + #NulltoZeroCols +', ('+ #SumCols+' FROM
(
SELECT
ISNULL(CAST(PartCode AS VARCHAR(30)),''Total'')PartCode,
SUM(StockQty)StockQty ,
ISNULL(Location,''Total'')Location
FROM #tblData
GROUP BY Location,PartCode
WITH CUBE
) x
PIVOT
(
MIN(StockQty)
FOR Location IN (' + #cols + ')
) p
ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode'
PRINT #query
EXEC SP_EXECUTESQL #query
Updated part will be,
SET #query = 'SELECT PartCode, Role, ' + #NulltoZeroCols + ' FROM
(
SELECT PartCode, Role, StockQty, Location
FROM #tblData
UNION ALL
SELECT PartCode, Role, SUM(StockQty), ''Total'' as Location
FROM #tblData
GROUP BY PartCode, Role
UNION ALL
SELECT
''Total'' PartCode,
''Total'' Role,
SUM(StockQty)StockQty ,
ISNULL(Location,''Total'')Location
FROM #tblData
GROUP BY Location
WITH cube
) x
PIVOT
(
MIN(StockQty)
FOR Location IN (' + #cols + ')
) p
ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode'
DECLARE #query NVARCHAR(MAX)
SET #query = 'SELECT p.PartCode, (SELECT TOP 1 Role FROM #tblData t3 WHERE t3.PartCode = p.PartCode and t3.Role = t2.Role ) Role, ' + #NullToZeroCols +', ('+ #SumCols+' FROM
(
SELECT
ISNULL(CAST(t1.PartCode AS VARCHAR(30)),''Total'')PartCode,
-- Role,
SUM(StockQty)StockQty ,
ISNULL(Location,''Total'')Location
FROM #tblData t1
GROUP BY Location,t1.PartCode
WITH CUBE
) x
PIVOT
(
MIN(StockQty)
FOR Location IN (' + #cols + ')
) p
left JOIN #tblData t2 on t2.PartCode = p.PartCode
GROUP BY t2.Role,p.PartCode, ' + #cols +'
ORDER BY CASE WHEN (p.PartCode=''Total'') THEN 1 ELSE 0 END,p.PartCode'
PRINT #query
EXEC (#query)

How to provide custom name to column in pivoting

I have a table like this:
id unit
1 mm
2 cm
3 kg
When I perform pivot operation on this, I am getting result as follows:
1 2 3
mm cm kg
Is it possible to get custom column names here, something like this:
d1 d2 d3
mm cm kg
I am using Pivot for this as:
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
GO
CREATE table #t
(id varchar(max),unit varchar(max))
insert into #t (id,unit)values
(1,'kg'),
(2,'cm'),
(3,'mm'),
(4,'m')
DECLARE #statement NVARCHAR(max)
,#columns NVARCHAR(max)
SELECT #columns = ISNULL(#columns + ',', '') + N'[' + cast(tbl.id as varchar(max)) + ']'
FROM (
SELECT DISTINCT id
FROM #t
) AS tbl
SELECT #statement = 'select *
INTO ##temp
from (
SELECT id,[unit]
FROM #t
) as s
PIVOT
(max(unit) FOR id in(' + #columns + ')) as pvt
'
EXEC sp_executesql #statement = #statement
SELECT * FROM ##temp
DROP TABLE #t
DROP TABLE ##temp
Is it possible?
Thanks
IF OBJECT_ID('tempdb..#t') IS NOT NULL
DROP TABLE #t
GO
CREATE TABLE #t (
id VARCHAR(10),
unit VARCHAR(100)
)
INSERT INTO #t (id, unit)
VALUES
('1', 'kg'),
('2', 'cm'),
('3', 'mm'),
('4', 'mm')
DECLARE #SQL NVARCHAR(MAX), #columns NVARCHAR(MAX)
SELECT #columns = STUFF((
SELECT ',[D' + id + ']'
FROM #t
FOR XML PATH('')), 1, 1, '')
SELECT #SQL = '
SELECT *
FROM (
SELECT [unit], col = N''D'' + id
FROM #t
) s
PIVOT (MAX(unit) FOR col IN (' + #columns + ')) p'
EXEC sys.sp_executesql #SQL
Just add a prefix to your ID. Example
SELECT #statement = 'select * INTO ##temp from
( SELECT [id] = ''d''+id,[unit] FROM #t ) as s
PIVOT
(max(unit) FOR id in(' + #columns + ')) as pvt '
Also it's terrible practice to use global temp tables! Especially one named ##temp
You can use a CASE expression with a dynamic sql query.
CREATE TABLE #t
(
id INT,
unit VARCHAR(2)
);
INSERT INTO #t VALUES
(1,'mm'),
(2,'cm'),
(3,'kg');
DECLARE #query AS VARCHAR(MAX);
SELECT #query = 'SELECT ' +
STUFF
(
(
SELECT DISTINCT ',MAX(CASE WHEN id = '+ CAST(id AS VARCHAR(10))
+ ' THEN unit END) AS d' + CAST(id AS VARCHAR(10))
FROM #t
FOR XML PATH('')
),
1,1,'');
SELECT #query += ' FROM #t;';
EXECUTE(#query);
Result
+----+----+----+
| d1 | d2 | d3 |
+----+----+----+
| mm | cm | kg |
+----+----+----+
SELECT #statement = 'select * INTO ##temp from ( SELECT ''d''+id AS [id],[unit] FROM #t ) as s PIVOT (max(unit) FOR id in(' + #columns + ')) as pvt '

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