Turn values into column names - sql

I have one table which contains some rows as below :
Sr. Name Product Qty
1 Yogesh ALB 1
2 Suresh AMS 2
3 Yogesh ALB 2
4 Mahesh MAS 5
Now, i want display records as in below style...
Sr. Name ALB AMS MAS
1 Yogesh 3 0 0
2 Suresh 0 2 0
3 Mahesh 5 0 0

BEGIN TRAN
CREATE TABLE #temp
(
Sr Int NOT null, Name Varchar(255), Product Varchar(255) , Qty numeric
)
INSERT INTO #temp
SELECT 1 ,'Yogesh', 'ALB', 1 UNION All
Select 2 , 'Suresh','AMS',2 UNION All
Select 3 , 'Yogesh' , 'ALB',2 UNION All
Select 4 , 'Mahesh','MAS',5
SELECT NAME,ISNULL(ALB,0) AS ALB,ISNULL(AMS,0) AS AMS,ISNULL(MAS,0) AS MAS
FROM (
SELECT
(Name) as Name,left(Product,3)as Product,
Isnull(Qty,0) as Qty
FROM #temp
) as s
PIVOT (SUM(QTY) FOR PRODUCT IN (ALB, AMS, MAS)) AS pvt
ORDER BY Name
ROLLBACK TRAN

Try with the below query.
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) [Sr.],Name,ISNULL(ALB,0) AS ALB,ISNULL(AMS,0) AS AMS,ISNULL(MAS,0) AS MAS
FROM (
SELECT Name,Product,
ISNULL(Qty,0) as Qty
FROM #temp
) as s
PIVOT (SUM(QTY) FOR PRODUCT IN (ALB, AMS, MAS)) AS pvt

Use
SELECT NAME,ISNULL(ALB,0) AS ALB,ISNULL(AMS,0) AS AMS,ISNULL(MAS,0) AS MAS
FROM
(SELECT NAME,PRODUCT,SUM(QTY) QTY FROM TABLENAME
GROUP BY NAME,PRODUCT) A
PIVOT(SUM(QTY) FOR PRODUCT IN (ALB,AMS,MAS)) AS PVT

Related

SQL Transpose row to columns

I am trying to transpose rows to columns but I didn't find any good answers.
Here is an example of what I want:
Input tables:
TABLE A
ID | NAME
1 | BOB
2 | JIM
3 | ROB
TABLE B
ID | CLUB
1 | 2
1 | 3
1 | 4
2 | 2
2 | 1
3 | 5
OUTPUT will be:
ID | CLUB1 | CLUB2 | CLUB3
1 | 2 | 3 | 4
2 | 2 | 1 |
3 | 5 | |
You need to enumerate the values to pivot them:
select id,
max(case when seqnum = 1 then club end) as club_1,
max(case when seqnum = 2 then club end) as club_2,
max(case when seqnum = 3 then club end) as club_3
from (select b.*,
row_number() over (partition by id order by club) as seqnum
from b
) b
group by id;
use conditional aggregation
select id,
max(case when id=1 then club end) club1,
max(case when id=2 then club end) club2,
max(case when id=3 then club end) club3
from tablename
group by id
use case when
select a.id,max(case when name='BOB' then CLUB end) ,
max(case when name='JIM' then CLUB end),
max(case when name='ROB' then CLUB end)
tablea a join tableb b on a.id=b.id group by a.id
Sample Data
IF OBJECT_ID('tempdb..#TempTab')IS NOT NULL
DROP TABLE #TempTab
;WITH CTE (ID,CLUB)
AS
(
SELECT 1 , 2 UNION ALL
SELECT 1 , 3 UNION ALL
SELECT 1 , 4 UNION ALL
SELECT 2 , 2 UNION ALL
SELECT 2 , 1 UNION ALL
SELECT 3 , 5
)
SELECT ID,
CLUB,
'CLUB'+CAST(ROW_NUMBER()OVER(PARTITION BY ID ORDER BY ID) AS VARCHAR) AS CLUBData
INTO #TempTab
FROM CTE
Dynamic sql
DECLARE #Column nvarchar(1000),#Column2 nvarchar(max),
#Sql nvarchar(max)
SELECT #Column =STUFF((SELECT DISTINCT ', '+QUOTENAME(CLUBData)
FROM #TempTab FOR XML PATH ('')),1,1,'')
SET #Sql = 'SELECT Id,'+#Column +'
FROM
(
SELECT * FROM #TempTab
) AS SRc
PIVOT
(
MAX(CLUB) FOR CLUBData IN ('+#Column+')
) AS pvt
'
PRINT #Sql
EXEC (#Sql)
Result
Id CLUB1 CLUB2 CLUB3
-------------------------
1 3 4 2
2 1 2 NULL
3 5 NULL NULL

How to find max value from each group and display their information when using "group by"

For example, i create a table about people contribue to 2 campaigns
+-------------------------------------+
| ID Name Campaign Amount (USD) |
+-------------------------------------+
| 1 A 1 10 |
| 2 B 1 5 |
| 3 C 2 7 |
| 4 D 2 9 |
+-------------------------------------+
Task: For each campaign, find the person (Name, ID) who contribute the most to
Expected result is
+-----------------------------------------+
| Campaign Name ID |
+-----------------------------------------+
| 1 A 1 |
| 2 D 4 |
+-----------------------------------------+
I used "group by Campaign" but the result have 2 columns "Campagin" and "max value" when I need "Name" and "ID"
Thanks for your help.
Edited: I fix some values, really sorry
You can use analytic functions for this:
select name, id, amount
from (select t.*, max(amount) over (partition by campaign) as max_amount
from t
) t
where amount = max_amount;
You can also do it by giving a rank/row_number partiton by campaign and order by descending order of amount.
Query
;with cte as(
select [num] = dense_rank() over(
partition by [Campaign]
order by [Amount] desc
), *
from [your_table_name]
)
select [Campaign], [Name], [ID]
from cte
where [num] = 1;
Try the next query:-
SELECT Campaign , Name , ID
FROM (
SELECT Campaign , Name , ID , MAX (Amount)
FROM MyTable
GROUP BY Campaign , Name , ID
) temp;
Simply use Where Clause with the max of amount group by Campaign:-
As following generic code:-
select a, b , c
from tablename
where d in
(
select max(d)
from tablename
group by a
)
Demo:-
Create table #MyTable (ID int , Name char(1), Campaign int , Amount int)
go
insert into #MyTable values (1,'A',1,10)
insert into #MyTable values (2,'B',1,5)
insert into #MyTable values (3,'C',2,7)
insert into #MyTable values (4,'D',2,9)
go
select Campaign, Name , ID
from #MyTable
where Amount in
(
select max(Amount)
from #MyTable
group by Campaign
)
drop table #MyTable
Result:-
Please find the below code for the same
SELECT *
FROM #MyTable T
OUTER APPLY (
SELECT COUNT(1) record
FROM #MyTable T1
where t.Campaign = t1.Campaign
and t.amount < t1.amount
)E
where E.record = 0

How to get values alternate for ROW_NUMBER()?

I have a table with values like these:
Name Order Innings
Suresh 1 1
Ramesh 2 1
Sekar 3 1
Raju 1 2
Vinoth 2 2
Ramu 3 2
I want the result be like this:
1stInn 2ndInn Order
Suresh Raju 1
Ramesh Vinoth 2
Sekar Ramu 3
I got the result using ROW_NUMBER() in SQL Server.
I want the same result in SQL Compact, But I can't use ROW_NUMBER() in SQL Compact.
I'm using SQL Compact version - 4.0.8482.1
How can I get the result?
Why do you need ROW_NUMBER()? you can use conditional aggregation using CASE EXPRESSION :
SELECT MAX(CASE WHEN t.innings = 1 THEN t.name END) as 1stInn,
MAX(CASE WHEN t.innings = 2 THEN t.name END) as 2sndInn,
t.Order
FROM YourTable t
GROUP BY t.order
simple Pivot will give the similar result
DECLARE #Table1 TABLE
( Name varchar(6), [Order] int, Innings int)
;
INSERT INTO #Table1
( Name , [Order] , Innings )
VALUES
('Suresh', 1, 1),
('Ramesh', 2, 1),
('Sekar', 3, 1),
('Raju', 1, 2),
('Vinoth', 2, 2),
('Ramu', 3, 2)
;
select [1] AS '1stinn',[2] AS '2ndinn',[order] from(
select Name , [Order] , Innings from #Table1)T
PIVOT (MAX(NAME) FOR Innings IN ([1],[2]))PVT

SQL query for excluding a key value matching record for a specific condition

I've a table as below :
declare #temp table(
PkId int,
DetailId int,
Type int
)
insert into #temp(PkId,DetailId,[Type])
select 1,1,5
union
select 2,1,3
union
select 3,1,4
union
select 4,2,5
union
select 5,3,5
union
select 6,3,3
select * from #temp order by DetailId
returns me
PkId DetailId TypeID
1 1 5
2 1 3
3 1 4
4 2 5
5 3 5
6 3 3
Conditions for getting the records are
For the given 'DetaildID' if only TypeID 5 is present, shall return 5
If 3 or 4 are present then exclude 5
I'm expecting the output as
2 1 3
3 1 4
4 2 5
6 3 3
Please help me with a query.
I don't understand the meaning of the rules, if not some sql puzzle, but it's possible to use the windowing function of SQLServer 2008 to write them
WITH C AS (
SELECT pkId, DetailId, typeID
, _34 = SUM(CASE WHEN TypeID IN (3, 4) THEN 1 ELSE 0 END)
OVER (PARTITION BY DetailId)
, _5 = SUM(TypeID) OVER (PARTITION BY DetailId)
FROM Table1
)
SELECT pkId, DetailId, typeID
FROM C
WHERE (_34 > 0 AND TypeID <> 5)
OR (_5 = 5)
SQLFiddle demo
For every row of a DetaildID group:
_34 is positive if there is a TypeID 3 or a TypeID 4 in the group
_5 will be 5 if the only TypeID in the group is 5
Those value are used in the WHERE condition of the main query to filter the data. The second condition (_5 = 5) don't check for the value of _34 as it's already implicit.
There should probably be a fallback condition in case TypeID has a value different from 3, 4 or 5, the query as it is will return them in a group with 3 or 4 (_34 > 0 AND TypeID <> 5) and remove it otherwise (_34 = 0 AND _5 <> 5).
select pkid, detailid, type
from temp
where type <> 5
group by pkid, detailid, type
union
select pkid, detailid, type
from temp
where detailid not in (
select detailid
from temp
where type <> 5
group by pkid, detailid, type
)
order by pkid
TEST

Create indexed view

My table structure is below :
MyTable (ID Int, AccID1 Int, AccID2 Int, AccID3 int)
ID AccID1 AccID2 AccID3
---- -------- -------- --------
1 12 2 NULL
2 4 12 1
3 NULL NULL 5
4 7 NULL 1
I want to create indexed view with below output :
ID Level Value
---- ----- -------
1 1 12
1 2 2
2 1 4
2 2 12
2 3 1
3 3 5
4 1 7
4 3 1
EDIT :
My table is very huge and I want to have above output.
I can Get my query such as below :
Select ID,
Case StrLevel
When 'AccID1' Then 1
When 'AccID2' Then 2
Else 3
End AS [Level],
AccID as Value
From (
Select A.ID, A.AccID1, A.AccID2, A.AccID3
From MyTable A
)as p
UNPIVOT (AccID FOR [StrLevel] IN (AccID1, AccID2, AccID3)) AS unpvt
or
Select *
from (
select MyTable.ID,
num.n as [Level],
Case Num.n
When 1 Then MyTable.AccID1
When 2 Then MyTable.AccID2
Else MyTable.AccID3
End AS AccID
from myTable
cross join (select 1
union select 2
union select 3)Num(n)
)Z
Where Z.AccID IS NOT NULL
or
Select A.ID,
2 AS [Level],
A.AccID1 AS AccID
From MyTable A
Where A.AccID1 IS NOT NULL
Union
Select A.ID,
2 AS [Level],
A.AccID2
From MyTable A
Where A.AccID2 IS NOT NULL
Union
Select A.ID,
3 AS [Level],
A.AccID3
From MyTable A
Where A.AccID3 IS NOT NULL
But Above query is slow and I want to have indexed view to have better performance.
and in indexed view I can't use UNION or UNPIVOT or CROSS JOIN in indexed view.
What if you created a Numbers table to essentially do the work of your illegal CROSS JOIN?
Create Table Numbers (number INT NOT NULL PRIMARY KEY)
Go
Insert Numbers
Select top 30000 row_number() over (order by (select 1)) as rn
from sys.all_objects s1 cross join sys.all_objects s2
go
Create view v_unpivot with schemabinding
as
Select MyTable.ID,
n.number as [Level],
Case n.number
When 1 Then MyTable.AccID1
When 2 Then MyTable.AccID2
Else MyTable.AccID3
End AS AccID
From dbo.Mytable
Join dbo.Numbers n on n.number BETWEEN 1 AND 3
go
Create unique clustered index pk_v_unpivot on v_unpivot (ID, [Level])
go
Select
ID,
[Level],
AccID
From v_unpivot with (noexpand)
Where AccID IS NOT NULL
Order by ID, [Level]
The WHERE AccID IS NOT NULL must be part of the query because derived tables are not allowed in indexed views.