This question already has answers here:
Efficiently convert rows to columns in sql server
(5 answers)
Closed 7 years ago.
I am trying to join two tables and then parse out the results into separate columns like so:
Table1:
Customer_ID
----------
1
2
3
Table2:
Customer_ID ListID
------------------
1 1
1 2
1 5
2 1
2 3
Desired Results:
Customer_ID ListID1 ListID2 ListID3
-----------------------------------
1 1 2 5
2 1 3
3
I used a LEFT JOIN to combine the tables and a GROUP BY to group columns with the same Custmer_ID as shown here:
SELECT MIN([Table1].[Customer_ID])
,MIN([Table2].[ListID])
FROM [Table1]
LEFT JOIN [Table2]
ON [Table2].[Customer_ID] = [Table1].[Customer_ID]
GROUP BY [Table1].[Customer_ID]
Current Results:
Customer_ID ListID
------------------
1 1
2 1
3 NULL
I can't figure out where to go from here to parse the ListID's into separate columns. Is there a way to iterate through the ListID's?
This is unique in that the column that you want to pivot for doesn't exist. You can create it with the Row_number window function. It looks like this:
SELECT Customer_ID, [1] ListID1, [2] ListID2, [3] ListID3
FROM
(select Table1.Customer_ID,
Table2.ListID,
ROW_NUMBER() over (Partition by Table1.Customer_ID Order By Table2.ListID) RowNum
from Table1
LEFT JOIN Table2
ON Table2.[Customer_ID] = Table1.[Customer_ID]) as SourceTable
PIVOT
(
max(ListID)
FOR RowNum IN ([1], [2], [3])
) AS PivotTable
This will only show the top three ListID values in the columns. You can add more RowNum values if you need more.
Related
I have a table on Snowflake
category
Metric1
Metric2
Metric3
First
1
2
3
Second
4
5
6
And I want my table to be like:
Metrics
First
Second
Metric1
1
4
Metric2
2
5
Metric3
3
6
I have a way of doing this with UNPIVOT function in Snowflake-SQL:
SELECT * FROM my_table
UNPIVOT
(DATA for Metrics in
(
Metric1,
Metric2,
Metric3
)
)
However, it somehow returns to
CATEGORY
METRICS
DATA
FIRST
Metric1
1
FIRST
Metric2
2
FIRST
Metric3
3
SECOND
Metric1
4
SECOND
Metric2
5
SECOND
Metric3
6
which is not something I want.
Could anyone please help me with this in one SQL query without creating a new table?
I think there is a way to solve this issue with UNPIVOT, but I couldn't figure this out. Thank you!
One method is a lateral join and aggregation:
select v.metric,
max(case when t.category = 'First' then v.value end) as first,
max(case when t.category = 'Second' then v.value end) as second
from t cross join lateral
(values ('Metric1', metric1),
('Metric2', metric2),
('Metric3', metric3)
) v(metric, value)
group by v.metric;
You were spot on in your original SQL ... just needed to PIVOT the Category back:
SELECT * FROM
(
SELECT * FROM CTE UNPIVOT
( DATA FOR METRICS IN (METRIC_1, METRIC_2, METRIC_3))
)
PIVOT (SUM (DATA) FOR CATEGORY IN ('FIRST','SECOND') )
Copy|Paste|Run
WITH CTE AS
(SELECT 'FIRST' CATEGORY, 1 METRIC_1 ,2 METRIC_2,3 METRIC_3
UNION
SELECT 'SECOND' CATEGORY, 4 METRIC_1 ,5 METRIC_2,6 METRIC_3)
SELECT * FROM
(
SELECT * FROM CTE UNPIVOT ( DATA FOR METRICS IN (METRIC_1, METRIC_2, METRIC_3))
)
PIVOT (SUM (DATA) FOR CATEGORY IN ('FIRST','SECOND') )
How to select the value from the table based on category_id?
I have a table like this. Please help me.
Table A
ID Name category_id
-------------------
1 A 1
2 A 1
3 B 1
4 C 2
5 C 2
6 D 2
7 E 3
8 E 3
9 F 3
How to get the below mentioned output from table A?
ID Name category_id
--------------------
1 A 1
2 A 1
4 C 2
5 C 2
7 E 3
8 E 3
Give a row number for each row based on group by category_id and sort by ascending order of ID. Then select the rows having row number 1 and 2.
Query
;with cte as (
select [rn] = row_number() over(
partition by [category_id]
order by [ID]
), *
from [your_table_name]
)
select [ID], [Name], [category_id]
from cte
where [rn] < 3;
Kindly run this query It really help You Out.
SELECT tbl.id,tbl.name, tbl.category_id FROM TableA as tbl WHERE
tbl.name IN(SELECT tbl2.name FROM TableA tbl2 GROUP BY tbl2.name HAVING Count(tbl2.name)> 1)
Code select all category_id from TableA which has Name entries more then one. If there is single entry of any name group by category_id then such data will be excluded. In above example questioner want to eliminate those records that have single Name entity like wise category_id 1 has name entries A and B among which A has two entries and B has single entry so he want to eliminate B from result set.
I have a table say StudentBillDetails and in this table data is saved annually and yrid is referenced to some other table. Now I am stuck with a problem. I want to retrieve non matching records as described below.
Stid BillNo Yrid
1 525 3
1 525 1
1 525 4
2 443 4
2 442 1
2 443 3
In above given table structure as you can see for three years StId 1 has same value but StId 2 has a confliction in Yrid 1. So I want to get these type of records.
If you just want to flag Stid values which have conflicts then the following simple query should work:
SELECT Stid
FROM yourTable
GROUP BY Stid
HAVING COUNT(DISTINCT BillNo) > 1
If you want the entire records you could try joining your table to the above query:
SELECT t1.*
FROM yourTable t1
INNER JOIN
( SELECT Stid FROM yourTable GROUP BY Stid HAVING COUNT(DISTINCT BillNo) > 1 ) t2
ON t1.Stid = t2.Stid
I have a table with the following columns.
EVAL_ID | GGRP_ID | GOAL_ID
1 1 1
2 2 1
2 2 2
3 1 3
I want to create a view with another columns called GOAL_VERSION which has values from 1 to 3. So that each row from the above table should be duplicated 5 times for different GOAL_VERSION numbers. The out put should be like this.
EVAL_ID | GGRP_ID | GOAL_ID |GOAL_VERSION
1 1 1 1
1 1 1 2
1 1 1 3
1 1 1 4
1 1 1 5
2 2 1 1
2 2 1 2
2 2 1 3
2 2 1 4
2 2 1 5
How can I do that. Help me. Thank you.
Is it this you are looking for?
DECLARE #tbl TABLE(EVAL_ID INT,GGRP_ID INT,GOAL_ID INT);
INSERT INTO #tbl VALUES
(1,1,1)
,(2,2,1)
,(2,2,2)
,(3,1,3);
SELECT tbl.*
,x.Nr
FROM #tbl AS tbl
CROSS JOIN (VALUES(1),(2),(3),(4),(5)) AS x(Nr)
EDIT: Varying count of repetition
DECLARE #tbl TABLE(EVAL_ID INT,GGRP_ID INT,GOAL_ID INT);
INSERT INTO #tbl VALUES
(1,1,1)
,(2,2,1)
,(2,2,2)
,(3,1,3);
DECLARE #tblCountOfRep TABLE(CountOfRep INT);
INSERT INTO #tblCountOfRep VALUES(3);
SELECT tbl.*
,y.Nr
FROM #tbl AS tbl
CROSS JOIN (SELECT TOP (SELECT CountOfRep FROM #tblCountOfRep) * FROM(VALUES(1),(2),(3),(4),(5) /*add the max count here*/) AS x(Nr)) AS y
In this case I'd prefer I numbers table...
Take a look at CROSS JOIN. If you make a table that's got one column with the 5 rows you want you can just CROSS JOIN it to get the result you're after.
You can achieve this using a CTE and CROSS APPLY:
;WITH CTE AS
(
SELECT 1 AS GOAL_VERSION
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
)
SELECT * FROM <your table>
CROSS APPLY CTE
use "with" (cte) with rank clause for creating view.
If you have a numbers table in SQL database, you can cross join your table with the numbers table for numbers between 1 and 5
Here is my SQL solution for your requirement
select
goals.*,
n.i as GOAL_VERSION
from goals, dbo.NumbersTable(1,5,1) n
And here is the modified version with "cross join" as suggested in the comments
select
goals.*,
n.i as GOAL_VERSION
from goals
cross join dbo.NumbersTable(1,5,1) n
You can realize, I used a SQL table-valued function for SQL numbers table
Please create that SQL function using the source codes given in the referred tutorial
I hope it helps,
I have a temp table with the following structure:
StudentID VALUE
1 5
2 NULL
and need to map the values from it to the table below:
StudentID DEPT
1 1
1 2
2 3
2 4
So the output should be like this:
StudentID DEPT VALUE
1 1 5
1 2 5
2 3 NULL
2 4 NULL
Do I need to use join or merge my table consisits of million record?
I have tried using joins but i am not getting exact what i need?
a JOIN. like this:
SELECT S.StudentId, S.Dept, V.Value
FROM Student AS S
JOIN #TEMP AS V
ON V.StudentId = S.StudentId
ORDER BY V.StudentId
SELECT table2.StudentID
,table2.DEPT
,#TEMP.Value
FROM table2
LEFT JOIN #TEMP
ON table2.StudentID = #TEMP.StudentID