How To Select specific column As Row? - sql-server

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

Related

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

SQL Server results into a single string with counter

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('')

How do I store the result of a query inside a temporary table in a stored procedure?

I am trying to store the results of a complex query inside a temporary table but I keep getting an error. Below is the code from my stored procedure:
DECLARE #TempItems TABLE
(
ID int IDENTITY, ForumThreadID int, ForumID int, ParentID int, title NVARCHAR(MAX), title_path NVARCHAR(MAX),
level_id NVARCHAR(MAX), level_id_path NVARCHAR(MAX), PostBody NVARCHAR(MAX), CreatedBy int, UserName NVARCHAR(50), Created DateTime
)
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = 'WITH TreeList (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path) as
(
SELECT p.ForumThreadID,
p.ForumID,
p.ParentID,
p.PostSubject,
CONVERT(nvarchar(max), p.ForumThreadID),
ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID),
RIGHT(''0000'' + CAST(ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID) AS varchar(max)),4)
FROM ForumThreads p
WHERE (p.ParentID = ' + #ParentID + ') AND (p.Deleted IS NULL)
UNION ALL
SELECT c.ForumThreadID,
c.ForumID,
c.ParentID,
c.PostSubject,
r.title_path + ''/'' + CAST(c.ForumThreadID AS VARCHAR(MAX)),
ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID),
CONVERT(varchar(max), r.level_id_path + ''.'' + RIGHT(''0000'' + CAST(ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID) AS VARCHAR),4))
FROM ForumThreads AS c
INNER JOIN treelist AS r
ON c.ParentID = r.ForumThreadID
WHERE (c.Deleted IS NULL))
SELECT TOP 100 TreeList.*, d.PostBody, d.CreatedBy, Members.UserName, COALESCE(d.Created,''1-JAN-1900'') AS Created
FROM TreeList INNER JOIN ForumThreads AS d ON TreeList.ForumThreadID = d.ForumThreadID INNER JOIN
Members ON d.CreatedBy = Members.MemberID
WHERE (d.Deleted IS NULL)
ORDER BY level_id_path;'
INSERT INTO #TempItems (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path, PostBody, CreatedBy, UserName, Created) EXEC #SQL
SELECT * FROM #TempItems
The error I am getting is:
Msg 203, Level 16, State 2, Procedure spPagedForumThreads, Line 53
The name 'WITH TreeList (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path) as
(
SELECT p.ForumThreadID,
p.ForumID,
p.ParentID,
p.PostSubject,
CONVERT(nvarchar(max), p.ForumThreadID),
ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID),
RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID) AS varchar(max)),4)
FROM ForumThreads p
WHERE (p.ParentID = 10720) AND (p.Deleted IS NULL)
UNION ALL
SELECT c.ForumThreadID,
c.ForumID,
c.ParentID,
c.PostSubject,
r.title_path + '/' + ' is not a valid identifier.
What am I doing wrong?
Is there another way to create a temporary table, one that does not require saving the query as a string?
Thanks!
What purpose does executing dynamic SQL serve? After your CTE, you should just be able to modify your SELECT statement to be INSERT INTO #TempItems SELECT TOP 100 TreeList.* .....
This should just work without needing dynamic SQL (i.e. EXEC). Note the statement prior to the WITH needs to be terminated with a semi-colon in order to be syntactically valid.
DECLARE #TempItems TABLE
(
ID int IDENTITY, ForumThreadID int, ForumID int, ParentID int, title NVARCHAR(MAX), title_path NVARCHAR(MAX),
level_id NVARCHAR(MAX), level_id_path NVARCHAR(MAX), PostBody NVARCHAR(MAX), CreatedBy int, UserName NVARCHAR(50), Created DateTime
);
WITH TreeList (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path) as
(
SELECT p.ForumThreadID,
p.ForumID,
p.ParentID,
p.PostSubject,
CONVERT(nvarchar(max), p.ForumThreadID),
ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID),
RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY ParentID ORDER BY p.ForumThreadID) AS varchar(max)),4)
FROM ForumThreads p
WHERE (p.ParentID = ' + #ParentID + ') AND (p.Deleted IS NULL)
UNION ALL
SELECT c.ForumThreadID,
c.ForumID,
c.ParentID,
c.PostSubject,
r.title_path + '/' + CAST(c.ForumThreadID AS VARCHAR(MAX)),
ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID),
CONVERT(varchar(max), r.level_id_path + '.' + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY c.ParentID ORDER BY c.ForumThreadID) AS VARCHAR),4))
FROM ForumThreads AS c
INNER JOIN treelist AS r
ON c.ParentID = r.ForumThreadID
WHERE (c.Deleted IS NULL))
INSERT INTO #TempItems (ForumThreadID, ForumID, ParentID, title, title_path, level_id, level_id_path, PostBody, CreatedBy, UserName, Created)
SELECT TOP 100 TreeList.*, d.PostBody, d.CreatedBy, Members.UserName, COALESCE(d.Created,'1-JAN-1900') AS Created
FROM TreeList INNER JOIN ForumThreads AS d ON TreeList.ForumThreadID = d.ForumThreadID INNER JOIN
Members ON d.CreatedBy = Members.MemberID
WHERE (d.Deleted IS NULL)
ORDER BY level_id_path;
SELECT * FROM #TempItems
EXEC(#SQL) instead of just EXEC #SQL.

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