SQL Server results into a single string with counter - sql-server

I have a table like this:
Product_Id Description
---------------------------
BX01 Desc 1
BxX1 Desc 2
Dss3 Desc 3
HHXY Desc 4
I want the result to be exactly:
1 - BX01, 2 - BxX1, 3 - Dss3, 4 - HHXY
I have this query:
DECLARE #ProID VARCHAR(8000)
SELECT #ProID = COALESCE(#ProID + ', - ', '') + Product_Id FROM TABLE
SELECT #ProID
but the return values is only :
BX01,- BxX1,- Dss3,- HHXY
The counting is missing.
How to do that?
Thanks

Assuming the numbers are the row numbers, you should be using ROW_NUMBER() (more info):
DECLARE #tmp TABLE (ID varchar(300), [Desc] varchar(300))
INSERT INTO #tmp (ID, [Desc])
SELECT 'BX01', 'Desc 1'
UNION
SELECT 'BxX1', 'Desc 2'
UNION
SELECT 'Dss3', 'Desc 3'
UNION
SELECT 'HHXY', 'Desc 4'
DECLARE #ProID VARCHAR(8000)
SELECT #ProID = COALESCE(#ProID + ', ', '') + CAST(t.row AS varchar(20))+ ' - ' + t.ID
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY ID) AS row, ID
FROM #tmp) AS t
SELECT #ProID

Try something like this using row_nu,mber function
SELECT CAST(row_number AS VARCHAR(5)) +' - '+ Product_Id +', '
from
(select Product_Id, ROW_NUMBER()OVER(order by Product_Id) as row_number
FROM TABLE ) as derived_tbl
FOR XML PATH('')

Related

How To Select specific column As Row?

I have 2 tables Phone_record and customer
In my phone records tables I have two columns company_name and ModelNo
Now I want to show Company_name as my main column name
And in this column I want to show models of that company like this
Company 1 company2.....
Model1 model1
Model2 model2
How to write this query?
Here is a fully functional example of how you might do this.
if OBJECT_ID('tempdb..#Something') is not null
drop table #Something
create table #Something
(
ID int,
Subject1 varchar(50)
)
insert #Something
select 10868952, 'Some Subject' union all
select 10868952, 'Another one' union all
select 10868952, 'This Subject' union all
select 10868952, 'Science' union all
select 12345, 'My Subject'
declare #MaxCols int
declare #StaticPortion nvarchar(2000) =
'with OrderedResults as
(
select *, ROW_NUMBER() over(partition by ID order by Subject1) as RowNum
from #Something
)
select ID';
declare #DynamicPortion nvarchar(max) = '';
declare #FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by ID order by ID';
with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --100 rows
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E2
)
select #DynamicPortion = #DynamicPortion +
', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then Subject1 end) as Subject' + CAST(N as varchar(6)) + CHAR(10)
from cteTally t
where t.N <=
(
select top 1 Count(*)
from #Something
group by ID
order by COUNT(*) desc
)
--select #StaticPortion + #DynamicPortion + #FinalStaticPortion
declare #SqlToExecute nvarchar(max) = #StaticPortion + #DynamicPortion + #FinalStaticPortion;
exec sp_executesql #SqlToExecute

Formatting SQL Server Query Output

I like to get the SQL Server query output in the following way. Currently my output is:
Class | Student ID | Student Name
------+------------+---------------
121 S1 Test 1
121 S2 Test 2
500 S22 Test a
500 S23 Test b
But I want the data output in the following way -
Class: 121
--------------------------------
Student ID | Student Name
-----------+---------------
S1 Test 1
S2 Test 2
Class: 500
--------------------------------
Student ID | Student Name
-----------+---------------
S22 Test a
S23 Test b
Could someone help me how can I achieve these?
Thanks
While I would agree SQL isn't the place to do your formatting.... sometimes you get stuck....
This Code
select '121' as Class, 'S1 ' as [Student ID], 'Test 1' as [Student Name] into #test
union select '121', 'S2 ', 'Test 2'
union select '500', 'S22 ', 'Test a'
union select '500', 'S23 ', 'Test b'
;
WITH class
AS (
SELECT DISTINCT class
FROM #test
)
,student
AS (
SELECT class
,(
SELECT STUFF((
SELECT CHAR(13) + t.[Student ID] + space(len('Student ID | ') - len(t.[Student ID])) + [Student Name]
FROM #Test t
WHERE t.[class] = class.[class]
FOR XML PATH('')
,type
).value('.[1]', 'nvarchar(max)'), 1, 1, '')
) AS info
FROM class
)
,theoutput
AS (
SELECT 'Class: ' + class + CHAR(13) + '------------------------' + CHAR(13) + 'Student ID | Student Name' + CHAR(13) + info + CHAR(13) + CHAR(13) AS txt
FROM student c
)
SELECT STUFF((
SELECT CHAR(13) + txt
FROM theoutput
FOR XML PATH('')
,type
).value('.[1]', 'nvarchar(max)'), 1, 1, '')
Will Produce
Class: 121
------------------------
Student ID | Student Name
S1 Test 1
S2 Test 2
Class: 500
------------------------
Student ID | Student Name
S22 Test a
S23 Test b
By using While loop we can get the Desired result Created sample data
IF OBJECT_ID('Tempdb..#TEMP') IS NOT NULL
Drop table #TEMP
;With cte(Class, StudentID, StudentName)
AS
(
SELECT 121,'S1' ,'Test 1' UNION ALL
SELECT 121,'S2' ,'Test 2' UNION ALL
SELECT 500,'S22','Test a' UNION ALL
SELECT 500,'S23','Test b'
)
SELECT * INTO #TEMP FROM CTe
SET NOCOUNT ON
DECLARE #CLassCOUnt INT
,#minID INT
,#maxid INT
,#Sql NVARCHAR(max)
,#SelectQuery INT
DECLARE #Table TABLE (
ID INT IDENTITY
,CLass INT
)
INSERT INTO #Table (CLass)
SELECT DISTINCT Class
FROM #TEMP
SELECT #minID = min(Id)
FROM #Table
SELECT #maxid = MAX(Id)
FROM #Table
WHILE (#minID <= #maxid)
BEGIN
SELECT #SelectQuery = Class
FROM #Table
WHERE ID = #minID
SELECT #Sql = 'SELECT Class, StudentID, StudentName FROM #TEMP WHERE Class=' + CAST(#SelectQuery AS VARCHAR)
PRINT 'Result Of Class:'+ CAST(#SelectQuery AS VARCHAR)+CHAR(13)+CHAR(10)+'------------------------'
PRINT #Sql
EXEC (#Sql)
SET #minID = #minID + 1
END
SET NOCOUNT OFF

Pivot with Group by on SQL

I'm create sql syntax which create pivot Group By Product based on Category
CREATE TABLE #Product ( Product varchar(10),Category varchar(10),Stock int)
INSERT INTO #Product Values ('Item A','CatA',10)
INSERT INTO #Product Values ('Item A','CatB',5)
INSERT INTO #Product Values ('Item B','CatA',3)
INSERT INTO #Product Values ('Item B','CatB',5)
INSERT INTO #Product Values ('Item B','CatC',7)
INSERT INTO #Product Values ('Item B','CatD',10)
SELECT *
FROM
(
SELECT Product,Category,Stock
FROM #Product A
) src
pivot
(
SUM(Stock)
for Category in ([CatA], [CatB], [CatC],[CatD])
) piv;
DROP TABLE #Product
Result of Query
Product CatA CatB CatC CatD
Item A 10 5 NULL NULL
Item B 3 5 7 10
Result trying to achieve is
Product Cat1 Stock1 Cat2 Stock2 Cat3 Stock3 Cat4 Stock4
Item A CatA 10 CatB 5 CatC 0 CatD 0
Item B CatA 3 CatB 5 CatC 7 CatD 10
Thanks for the help
You need to create all combinations of Product and Category first. Then do a LEFT JOIN on #Product to get the Stock. Finally, use the result to pivot the data.
Since I'm not familiar with the PIVOT command, I used another technique called Dynamic Crosstab
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql =
'SELECT
Product' + CHAR(10);
SELECT #sql = #sql +
STUFF((
SELECT
' ,MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), t.RN) + ' THEN Category END) AS ' + QUOTENAME('Cat' + CONVERT(VARCHAR(3), t.RN)) + CHAR(10) +
' ,MAX(CASE WHEN RN = ' + CONVERT(VARCHAR(3), t.RN) + ' THEN Stock END) AS ' + QUOTENAME('Stock' + CONVERT(VARCHAR(3), t.RN)) + CHAR(10)
FROM (
SELECT DISTINCT
RN = ROW_NUMBER() OVER(PARTITION BY Product ORDER BY(SELECT NULL))
FROM #Product
) t
FOR XML PATH('')
), 1, 1, ' ');
SELECT #sql = #sql +
'FROM(
SELECT
p1.Product,
p1.Category,
Stock = ISNULL(p2.Stock, 0),
RN = ROW_NUMBER() OVER(PARTITION BY p1.Product ORDER BY p1.Category)
FROM (
SELECT
t1.Product, t2.Category
FROM (
SELECT DISTINCT Product FROM #Product
) t1
CROSS JOIN (
SELECT DISTINCT Category FROM #Product
) t2
) p1
LEFT JOIN #Product p2
ON p1.Product = p2.Product
AND p1.Category = p2.Category
)t
GROUP BY Product;';
PRINT #sql;
EXEC sp_executesql #sql;
ONLINE DEMO

how shall i transpose rows into new columns only if duplicates appears in rows?

I have a table like this:
I need to get output like this:
I tried to use transposing, but I am not getting someone please give idea to do this.
Creation script for table:
CREATE TABLE #T1 (
itemid int,
pack int,
UOM nvarchar(2)
)
INSERT INTO #T1 VALUES
(1,1,'EA'),
(1,10,'BX'),
(1,100,'CA'),
(2,1,'EA'),
(2,10,'RL')
If you need simple, fixed column solution, you can use:
SELECT * INTO #temp FROM
(VALUES
(1, 1, 'EA'),
(1, 10, 'BX'),
(1, 100, 'CA'),
(2, 1, 'EA'),
(2, 10, 'RL')) T(ItemId, Pack, UOM)
SELECT ItemId, MAX([1]) Pack1, MAX([U1]) UOM1, MAX([2]) Pack1, MAX([U2]) UOM1, MAX([3]) Pack1, MAX([U3]) UOM1 FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack) PackNum,
'U'+CONVERT(varchar(10), ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack)) UOMNum
FROM #temp
) T
PIVOT
(
MAX(Pack) FOR PackNum IN ([1], [2], [3])
) PPack
PIVOT
(
MAX(UOM) FOR UOMNum IN ([U1],[U2],[U3])
) PUOM
GROUP BY ItemId
If number of columns is not fixed, you must do it dynamically (see #gofr1) or:
DECLARE #count TABLE(N varchar(10))
INSERT #count
SELECT CONVERT(varchar(10), ROW_NUMBER() OVER (ORDER BY (SELECT 1)))
FROM #temp WHERE ItemId =
(
SELECT TOP 1 ItemId
FROM #temp
GROUP BY ItemId
ORDER BY COUNT(*) DESC
)
DECLARE #select varchar(MAX) = STUFF((SELECT ', MAX(['+N+']) Pack'+N+', MAX([U'+N+']) UOM'+N FROM #count FOR XML PATH('')), 1, 2, '')
DECLARE #pivot1 varchar(MAX) = STUFF((SELECT ', ['+N+']' FROM #count FOR XML PATH('')), 1, 2, '')
DECLARE #pivot2 varchar(MAX) = STUFF((SELECT ', [U'+N+']' FROM #count FOR XML PATH('')), 1, 2, '')
DECLARE #sql varchar(MAX) = '
SELECT ItemId, '+#select+' FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack) PackNum,
''U''+CONVERT(varchar(10), ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack)) UOMNum
FROM #temp
) T
PIVOT
(
MAX(Pack) FOR PackNum IN ('+#pivot1+')
) PPack
PIVOT
(
MAX(UOM) FOR UOMNum IN ('+#pivot2+')
) PUOM
GROUP BY ItemId'
EXEC(#sql)
Dynamic SQL and some pivoting:
DECLARE #sql nvarchar(max),
#columns nvarchar(max)
SELECT #columns = (
SELECT DISTINCT ','+QUOTENAME('pack' + cast(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY itemid) as nvarchar(max)))+','+
QUOTENAME('UOM'+ cast(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY itemid) as nvarchar(max)))
FROM #T1
FOR XML PATH('')
)
SELECT #sql = N'
SELECT *
FROM (
SELECT itemid,
Items+rn as Items,
[Values]
FROM (
SELECT itemid,
CAST(UOM as nvarchar(max)) as UOM,
CAST(pack as nvarchar(max)) as pack,
CAST(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY (SELECT NULL)) as nvarchar(max)) as rn
FROM #T1
) as t
UNPIVOT (
[Values] FOR Items in ([UOM],[pack])
) as up
) t1
PIVOT (
MAX([Values]) FOR Items IN ('+STUFF(#columns,1,1,'')+')
) as pvt'
EXEC sp_executesql #sql
Output:
itemid pack1 UOM1 pack2 UOM2 pack3 UOM3
1 1 EA 10 BX 100 CA
2 1 EA 10 RL NULL NULL
EDIT#1
There is one more way:
DECLARE #sql nvarchar(max),
#columns nvarchar(max),
#colsrn nvarchar(max)
;WITH cte AS (
SELECT DISTINCT cast(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY itemid) as nvarchar(max)) as rn
FROM #T1
)
SELECT #columns = (
SELECT ',MAX('+QUOTENAME('pack' + rn) +') as '+ QUOTENAME('pack' + rn) +',MAX('+
QUOTENAME('UOM'+ rn) +') as ' + QUOTENAME('UOM'+ rn)
FROM cte
FOR XML PATH('')
),
#colsrn = (
SELECT DISTINCT ',CASE WHEN rn = ' + rn +' THEN '+QUOTENAME('pack')+' ELSE NULL END as [pack'+rn+'],'
+'CASE WHEN rn = ' + rn +' THEN '+QUOTENAME('UOM')+' ELSE NULL END as [UOM'+rn+']'
FROM cte
FOR XML PATH('')
)
SELECT #sql = N'
SELECT itemid'+#columns+'
FROM (
SELECT itemid'+#colsrn+'
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY (SELECT NULL)) as rn
FROM #T1
) as t
) s
GROUP BY s.itemid'
EXEC sp_executesql #sql
Same output.
select itemid,
max(case when seq = 1 then pack end) pack1, max(case when seq = 1 then uom end)uom1,max(case when seq = 2 then pack end) pack2, max(case when seq = 2 then uom end) uom2,
max(case when seq = 3 then pack end) pack3, max(case when seq = 3 then uom end) uom3
from
(
select itemid, pack, uom, row_number() over(partition by itemid order by itemid) seq from T1
) d
group by itemid

Pivot table without knowing row values

This is my table - Select ItemName, ItemDescription from MyTable
I do not know what the values would be in ItemName or ItemDescription.
Would it be possible to display the data so that ItemName would be created as columns and the ItemDescription be the row value?
Requires mssql 2008+
create table mytable( ItemName varchar(10), ItemDescription varchar(10))
insert mytable values('item 1', 'desc1')
insert mytable values('item 2', 'desc2')
insert mytable values('item 1', 'desc2')
declare #list varchar(2000)
;with cte
as(
select distinct top 100 percent replace(replace(itemname, ']', ''), '[', '') itemname
from mytable
order by itemname
)
select #list = coalesce(#list + ',' + '['+itemname+']', '['+itemname+']') from cte
declare #sql varchar(4000)
set #sql =
'
select * from
(
select replace(replace(itemname, '']'', ''''), ''['', '''') itemname, ItemDescription, row_number() over (partition by ItemName order by ItemDescription) id from mytable
) a
PIVOT (MAX([ItemDescription]) FOR [itemname] IN ('+#list+')) AS pvt'
exec (#sql)
Result:
id item 1 item 2
1 desc1 desc2
2 desc2 NULL

Resources