enter image description hereI have 5 columns and i want to get values from those 5 columns and put them into a single column.
+---------------+----------+----------+----------+---------------+
| Option_1 | Option_2 | Option_3 | Option_4 | Option_5 |
+---------------+----------+----------+----------+---------------+
| Below average | Average | Good | Better | Above average |
+---------------+----------+----------+----------+---------------+
So in output i want Below Average, Average, Good, Better and above Average in one column Named Option
Union all can be done:
SELECT
Option1 AS Options
FROM (SELECT
option1
FROM tablename
UNION ALL
SELECT
option2
FROM tablename
UNION ALL
SELECT
option3
FROM tablename
UNION ALL
SELECT
option4
FROM tablename
UNION ALL
SELECT
option5
FROM tablename) tablename;
or
UNPIVOT performs almost the reverse operation of PIVOT, by rotating columns into rows.
SELECT
opt.Options
FROM (SELECT
*
FROM yourtable) t
UNPIVOT (Options FOR tables IN ([Option_1], [Option_2], [Option_3], [Option_4], [Option_5])) AS opt
ORDER BY tables;
For more info please visit: https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot
declare #table table( Option_1 varchar(50),Option_2 varchar(50), Option_3 varchar(50), Option_4 varchar(50), Option_5 varchar(50))
insert into #table
select 'Below average', 'Average', 'Good','Better','Above average'
select p.typename,p.numericvalue from (
select *
from #table
) a
unpivot(numericvalue for typename in([Option_1] ,[Option_2] , [Option_3] , [Option_4] , [Option_5] )) as p
order by typename
output
typename numericvalue
Option_1 Below average
Option_2 Average
Option_3 Good
Option_4 Better
Option_5 Above average
Sample Data
IF OBJECT_ID('dbo.Sampletable')IS NOT NULL
DROP TABLE Sampletable
GO
CREATE TABLE Sampletable (
Option_1 varchar(50)
,Option_2 varchar(50)
,Option_3 varchar(50)
,Option_4 varchar(50)
,Option_5 varchar(50)
)
INSERT INTO Sampletable
SELECT 'Below average', 'Average', 'Good','Better','Above average'
Using Dynamic Sql and Cross apply we get the expected result
DECLARE #DynamicCol nvarchar(max),#Sql nvarchar(max)
SELECT #DynamicCol=
STUFF((SELECT ', '+'('+''''+COLUMN_NAME+''''+','+ COLUMN_NAME +')'FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='Sampletable'
FOR XML PATH ('')),1,1,'')
SET #Sql='
SELECT Typename
,Numericvalue
FROM Sampletable t
CROSS APPLY (VALUES '+#DynamicCol+
') AS dt (Typename,Numericvalue )'
PRINT #Sql
EXEC (#Sql)
Sample demo
Result
Typename Numericvalue
-------------------------
Option_1 Below average
Option_2 Average
Option_3 Good
Option_4 Better
Option_5 Above average
SELECT CONCAT(Option_1,', ',Option_2,', ',Option_3,' ,',Option_4,',',Option_5) as Option
FROM TAble1
if you want results as a one column but multiple rows
SELECT Option_1 AS Option FROM Table1
UNION ALL
SELECT Option_2 AS Option FROM Table1
UNION ALL
SELECT Option_3 AS Option FROM Table1
UNION ALL
SELECT Option_4 AS Option FROM Table1
UNION ALL
SELECT Option_5 AS Option FROM Table1
Using UNPIVOT
SELECT
rslt.Options
FROM (SELECT
*
FROM Table1 ) AS dt
UNPIVOT (Options FOR tables IN ([Option_1], [Option_2], [Option_3], [Option_4], [Option_5])) AS rslt
Sample Link
Related
I have a table candidate
id candidate_name
---------------------------
1 john
2 mary
and another table units
id name
--------
1 unit1
2 unit2
3 unit3
i would like to generate an output as
id candidate_name unit1 unit2 unit3
---------------------------------------
1 john null null null
2 mary null null null
Any way I can achieve this?
your data
CREATE TABLE candidate(
id int NOT NULL
,candidate_name VARCHAR(40)
);
INSERT INTO candidate
(id,candidate_name) VALUES
(1,'john'),
(2,'mary');
CREATE TABLE units(
id int NOT NULL
,name VARCHAR(50)
);
INSERT INTO units
(id,name) VALUES
(1,'unit1'),
(2,'unit2'),
(3,'unit3');
you should use Cross Join and Pivot
select
*
from
(
select
c.id,
candidate_name,
cast(null as int) id1,
name
from
candidate c
CROSS JOIN units u
) src pivot (
max(id1) for name in ([unit1], [unit2], [unit3])
) piv;
using Dynamic Sql
DECLARE #SQL nvarchar(max);
DECLARE #names nvarchar(1000)= (
SELECT STRING_AGG(concat('[',name,']'),',')
WITHIN GROUP (order by id) from units)
set #SQL='select
*
from
(
select
c.id,
candidate_name,
cast(null as int) id1,
name
from
candidate c
CROSS JOIN units u
) src pivot (
max(id1) for name in ('+ #names +' )
) piv;'
exec(#SQL)
dbfiddle
I have two tables: MainTable and MyTable. MyTable has unique ControlNo and ID. I need to add very first EffDate from MainTable to MyTablebased on ID and ControlNo.
For that I need to look at PreviousID column, then see if that PreviousID is in ID column and so on.
Desired output should look like this:
The below is an example with dummy data of getting proper EffDate by supplying an ID value. It works, but how can I loop through the whole MainTable, retrieve ID's and EffDate into separate table, then join that table to MyTable?
-- function returns PreviousID based on ID
CREATE FUNCTION [dbo].[GetPriorQuoteID](#ID varchar(50))
RETURNS varchar(50)
AS
BEGIN
DECLARE #RetVal varchar(50)
SET #RetVal = NULL
SELECT TOP 1 #RetVal = MainTable.PreviousID
FROM MainTable
WHERE MainTable.ID = #ID
RETURN #RetVal
END
-- create sample table
IF OBJECT_ID('MainTable') IS NOT NULL DROP TABLE MainTable;
select 3333 as ControlNo, 'QuoteID3' as ID, 'QuoteID2' as PreviousID, '2020-08-25' as EffDate
into MainTable
union all select 2222 as COntrolNo, 'QuoteID2', 'QuoteID1', '2019-08-25'
union all select 1111 as COntrolNo, 'QuoteID1', NULL, '2018-08-25'
union all select 7777 as COntrolNo, 'QuoteID6', 'QuoteID5', '2020-02-10'
union all select 6666 as COntrolNo, 'QuoteID5', NULL, '2019-02-10'
select * from MainTable
DECLARE #PriorQuote varchar(50)
DECLARE #RetVal VARCHAR(50) = ''
DECLARE #ControlNo INT
DECLARE #ID varchar(50) = 'QuoteID3'
SELECT TOP 1 #ControlNo = MainTable.ControlNo FROM MainTable WHERE MainTable.ID = #ID
Set #PriorQuote = #ID
SELECT TOP 1 #PriorQuote = MainTable.ID FROM MainTable WHERE MainTable.ControlNo = #ControlNo
WHILE dbo.GetPriorQuoteID(#PriorQuote) IS NOT NULL AND dbo.GetPriorQuoteID(#PriorQuote)<> #PriorQuote
BEGIN
SET #PriorQuote = dbo.GetPriorQuoteID(#PriorQuote)
END
SELECT TOP 1 #RetVal = CONVERT(VARCHAR(10), MainTable.EffDate, 101)
FROM MainTable
WHERE MainTable.ID = #PriorQuote
SELECT #RetVal
-- clean up
drop table MainTable
drop function GetPriorQuoteID
UPDATE: Adding dummy data tables
-- create sample table #MainTable
IF OBJECT_ID('tempdb..#MainTable') IS NOT NULL DROP TABLE #MainTable;
create table #MainTable (ControlNo int, ID varchar(50), PreviousID varchar(50), EffDate date)
insert into #MainTable values
(3333,'QuoteID3','QuoteID2', '2020-08-25'),
(2222,'QuoteID2','QuoteID1', '2019-08-25'),
(1111,'QuoteID1',NULL, '2018-08-25'),
(7777,'QuoteID6','QuoteID5', '2020-02-10'),
(6666,'QuoteID5',NULL, '2019-02-10')
--select * from #MainTable
-- create sample table #MyTable
IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable;
create table #MyTable (ControlNo int, ID varchar(50), EffDate date)
insert into #MyTable values
(3333,'QuoteID3',NULL),
(7777,'QuoteID6',NULL)
--select * from #MyTable
You can use a recursive query to traverse the hierarchy.
I would start by joining the original table with the main table, which restricts the paths to just the rows we are interested in. Then, you can recurse towards the parent. Finally, we need to filter on the top parent per path: top() and row_number() come handy for this.
Consider:
with cte as (
select t.controlno, t.id, m.previousid, m.effdate, 1 lvl
from #maintable m
inner join #mytable t on t.controlno = m.controlno and t.id = m.id
union all
select c.controlno, c.id, m.previousid, m.effdate, c.lvl + 1
from cte c
inner join #maintable m on m.id = c.previousid
)
select top(1) with ties controlno, id, effdate
from cte
order by row_number() over(partition by controlno, id order by lvl desc)
Demo on DB Fiddle:
controlno | id | effdate
--------: | :------- | :---------
3333 | QuoteID3 | 2018-08-25
7777 | QuoteID6 | 2019-02-10
using CTE like below you can get the desired results.
See live demo
Learn more about recursive CTEs here
; with cte as
(
select EffDate, ControlNo, ID, Level=1 from MainTable
where PreviousID is NULL
union all
select C.EffDate, M.ControlNo, M.ID, Level=Level+1 from MainTable AS M
join cte as C on C.ID=M.PreviousID
)
select MyTable.*,cte.EffDate from cte join MyTable on Mytable.ID=cte.ID
You can use a recursive CTE for this:
WITH cte
AS
(
SELECT m.ID,m.PreviousID
FROM MainTable m
JOIN MainTable m2
ON m.previousID = m2.ID
WHERE m2.previousID IS NULL
UNION ALL
SELECT m2.ID,cte.previousID
FROM cte
JOIN MainTable m2
ON m2.previousID = cte.ID
)
SELECT *
FROM cte;
Here is a working example of the CTE approach with the table provided
;with recur_cte(ControlNo, ID, PreviousID, EffDate, HLevel) as (
select mt.ControlNo, cast(null as varchar(100)), mt.PreviousID, mt.EffDate, 1
from MainTable mt
where not exists(select 1
from MainTable mt_in
where mt.ID=mt_in.PreviousID)
union all
select rc.ControlNo, rc.ID, mt.PreviousID, mt.EffDate, rc.HLevel+1
from recur_cte rc
join MainTable mt on rc.PreviousID=mt.ID and rc.EffDate>mt.EffDate)
select * from recur_cte;
Results
ControlNo ID PreviousID EffDate HLevel
3333 NULL QuoteID2 2020-08-25 1
7777 NULL QuoteID5 2020-02-10 1
7777 NULL NULL 2019-02-10 2
3333 NULL QuoteID1 2019-08-25 2
3333 NULL NULL 2018-08-25 3
I have a table (result of selecting from some table, ordered by the Change column) like this:
ID Change
1001 4
1002 4
1003 4
1004 3
1005 3
1006 2
... ...
And I want to update another table with above data as below:
update sometable set columnA=columnA + 4 where ID in (1001, 1002, 1003)
update sometable set columnA=columnA + 3 where ID in (1004, 1005)
update sometable set columnA=columnA + 2 where ID in (1006)
...
How could I perform this with SQL command?
try this in Test sample data,
declare #t table(ID int,Change int)
insert into #t values (1001,4),(1002,4),(1003,4),(1004,3),(1005,3),(1006,2)
update s set s.columnA=s.columnA + t.change
from sometable S
inner join #t t on s.id=t.id
For your case the below is schema..
CREATE TABLE #TAB(ID INT, Change INT)
INSERT INTO #TAB
SELECT 1001 , 4
UNION ALL
SELECT 1002, 4
UNION ALL
SELECT 1003 , 4
UNION ALL
SELECT 1004, 3
UNION ALL
SELECT 1005 , 3
UNION ALL
SELECT 1006, 2
Now we can handle it using For XML Path and Stuff and a CTE as below
;WITH CTE AS(
SELECT DISTINCT CHANGE
,STUFF( (SELECT ', '+CAST(ID AS VARCHAR(100)) FROM #TAB T2
WHERE T2.Change= T.CHANGE FOR XML PATH('')),1,1,'') ID_PK FROM #TAB T
)
SELECT 'UPDATE SOMETABLE SET COLUMN_A= COLUMN_A+ '+CAST(CHANGE AS VARCHAR(10))+' WHERE ID IN ('+ID_PK +') ;' FROM CTE
I have a table like this one
RowNum | TranNo | nTotalSales | nBalance
1 | 1 | 800 | 0
and I want to display it this way
RowNum | 1
cTranNo | 1
nTotalSales | 800
nBalance | 0
How can I do this?
Here is a complete working example, when you you do an UNPIVOT, which is what your are asking for, your 'value' types need to be of the same type, so cast them however you want. In my example, I have cast them all to VARCHAR(20):
DECLARE #bob TABLE
(
RowNum INT,
TranNo INT,
nTotalSales INT,
nBalance INT
);
INSERT INTO #bob(RowNum, TranNo, nTotalSales, nBalance)
VALUES(1, 1, 800, 0);
WITH T AS (
SELECT CAST(RowNum AS VARCHAR(20)) AS RowNum,
CAST(TranNo AS VARCHAR(20)) AS TranNo,
CAST(nTotalSales AS VARCHAR(20)) AS nTotalSales,
CAST(nBalance AS VARCHAR(20)) AS nBalance
FROM #bob
)
SELECT attribute, value
FROM T
UNPIVOT(value FOR attribute IN(RowNum, TranNo, nTotalSales, nBalance)) AS U;
SELECT 'RowNum' TITLE, RowNum AS [VALUE]
FROM TABLE
UNION ALL
SELECT 'TranNo', TranNo
FROM TABLE
UNION ALL
SELECT 'nTotalSales', nTotalSales
FROM TABLE
UNION ALL
SELECT 'nBalance', nBalance
FROM TABLE
It's not real fun, but here's one solution:
SELECT 'RowNum', RowNum FROM tbl
UNION
SELECT 'cTranNo', TranNo FROM tbl
UNION
SELECT 'nTotalSales', nTotalSales FROM tbl
UNION
SELECT 'nBalance', nBalance FROM tbl
That will turn the columns into rows. If you want each of the column-rows to be interlaced, you may need to introduce a record number along with some sorting.
That would look like this:
SELECT 'RowNum' AS ColName, RowNum AS [Value], RowNum FROM tbl
UNION
SELECT 'cTranNo' AS ColName, TranNo, RowNum FROM tbl
UNION
SELECT 'nTotalSales' AS ColName, nTotalSales, RowNum FROM tbl
UNION
SELECT 'nBalance' AS ColName, nBalance, RowNum FROM tbl
ORDER BY RowNum, ColName
If I had this structure with the columns:
Primary_Key, Name, Parent_Primary_ID, DISPLAY_ORDER
1 Event NULL 1
2 News NULL 2
3 Event_List 1 1
4 Event_Detail 1 2
5 News_List 2 1
6 News_Details 2 2
how would you return data like:
1 Event
3 Event_List
4 Event_Detail
2 News
5 News_List
6 News_Detail
Thanks
Rob
If SQL Server 2005+
DECLARE #YourTable TABLE
(Primary_Key INT PRIMARY KEY,
Name VARCHAR(100),
Parent_Primary_ID INT NULL,
DISPLAY_ORDER INT)
INSERT INTO #YourTable
SELECT 1,'Event',NULL,1 UNION ALL
SELECT 2,'News',NULL,2 UNION ALL
SELECT 3,'Event_List',1,1 UNION ALL
SELECT 4,'Event_Detail',1,2 UNION ALL
SELECT 5,'News_List',2,1 UNION ALL
SELECT 6,'News_Details',2,2;
WITH Hierarchy
AS (SELECT *,
path = CAST(DISPLAY_ORDER AS VARCHAR(100))
FROM #YourTable
WHERE Parent_Primary_ID IS NULL
UNION ALL
SELECT y.Primary_Key,
y.Name,
y.Parent_Primary_ID,
y.DISPLAY_ORDER,
CAST(path + '.' + CAST(y.DISPLAY_ORDER AS VARCHAR) AS VARCHAR(100))
FROM #YourTable y
JOIN Hierarchy h
ON h.Primary_Key = y.Parent_Primary_ID)
SELECT Primary_Key,
Name
FROM Hierarchy
ORDER BY path
Try (asumming standardish sql is supported)
DECLARE #YourTable TABLE
(Primary_Key INT PRIMARY KEY,
Name VARCHAR(100),
Parent_Primary_ID INT NULL,
DISPLAY_ORDER INT)
INSERT INTO #YourTable
SELECT 1,'Event',NULL,1 UNION ALL
SELECT 2,'News',NULL,2 UNION ALL
SELECT 3,'Event_List',1,1 UNION ALL
SELECT 4,'Event_Detail',1,2 UNION ALL
SELECT 5,'News_List',2,1 UNION ALL
SELECT 6,'News_Details',2,2;
select
primary_key = t1.primary_key,
name = t1.name
from
#YourTable t1
left join #YourTable t2 on t1.parent_primary_id = t2.Primary_Key
order by
coalesce(t2.DISPLAY_ORDER,t1.DISPLAY_ORDER,0),
case
when t2.Primary_Key is null then 0
else t1.DISPLAY_ORDER
end
I don't see any grouping in your results. Unless you are trying to do something you aren't telling us I would use the query below:
SELECT Primary_Key, Name FROM YourTable
I don't see how you are ordering those results so I didn't try to order them.