I have the following table:
oDate value1 value2 value3 value4
2014-06-01 10 20 30 40
2014-06-02 20 25 35 50
I want to have the following result
oDate oField oValue
2014-06-01 Value1 10
2014-06-01 Value2 20
2014-06-01 Value3 30
2014-06-01 Value4 40
Is it possible to do that in SQL?
Need advice. Cheers,
You could do this:
Test data:
DECLARE #tbl TABLE(oDate DATETIME,value1 INT,value2 INT,value3 INT,value4 INT)
INSERT INTO #tbl
VALUES
('2014-06-01',10,20,30,40),
('2014-06-02',20,25,35,50)
UNPIVOT query
SELECT
*
FROM
(
SELECT
oDate,
value1,
value2,
value3,
value4
FROM
#tbl
) sourceTable
UNPIVOT
(
oField FOR oValue IN
(value1,value2,value3,value4)
) AS unpvt
Reference:
Using PIVOT and UNPIVOT
Try this
SELECT DISTINCT ODATE,VALUE,FIELD
FROM
(SELECT odate,value1,value2,value3,value4
FROM #temp) p
UNPIVOT
(VALUE FOR FIELD IN
(value1,value2,value3,value4)
)AS unpvt;
GO
How about this?
select
oDate,
'Value1' as oField,
value1 as oValue
from yourTable
union all
select
oDate,
'Value2' as oField,
value2 as oValue
from yourTable
union all
select
oDate,
'Value3' as oField,
value3 as oValue
from yourTable
union all
select
oDate,
'Value4' as oField,
value4 as oValue
from yourTable
order by oDate, oField
Related
My table:
Column1
Date
Value1
1-Feb
Value2
1-Feb
Value2
2-Feb
Value3
2-Feb
Value1
3-Feb
Value2
3-Feb
Value4
3-Feb
Expected Output:
Column1
Date
Status
Value1
1-Feb
Added
Value2
1-Feb
Added
Value1
2-Feb
Closed
Value3
2-Feb
Added
Value1
3-Feb
Added
Value3
3-Feb
Closed
Value4
3-Feb
Added
How to get the records that have been added or closed between certain dates in a table in SQL
I'm executing an except command between each date and vice versa then inserting data into a table.
Is there any way I can achieve the desired output with a single query?
I'm currently using this solution.
SELECT column1, 'Added' AS Status FROM mytable WHERE date = '2023-02-03' EXCEPT SELECT column1 FROM mytable WHERE date = '2023-02-02'
UNION
SELECT column1, 'Closed' AS Status FROM mytable WHERE date = '2023-02-02' EXCEPT SELECT column1 FROM mytable WHERE date = '2023-02-03'
You can do it by generating the upcoming days for every column with no upcoming day, then with left join you can get the Status.
with cte as (
select column1, DATEADD(day, 1, min(Date)) AS Date
from mytable
where Date < (select max(Date) from mytable)
group by column1
having count(1) = 1
union
select column1, Date
from mytable
),
cte2 as (
select c.*, iif(t.Date is not null, 'Added', 'Closed') as status
from cte c
left join mytable t on t.column1 = c.column1 and t.Date = c.Date
)
select column1, min(Date) as Date, status
from cte2
group by column1, status
order by min(Date), column1;
Demo here
I have the current situation:
TableA
----------
SN Date OpsID
1234 2018-02-12 1
1324 2018-02-12 2
2134 2018-02-13 3
TableB
----------
Name String Number OpsID
Value1 Hello NULL 1
Value2 NULL 1111 1
Value3 Apples NULL 1
Value1 There NULL 2
Value2 NULL 2222 2
Value3 Pears NULL 2
Value1 Baby NULL 3
Value2 NULL 3333 3
Value3 Bananas NULL 3
...and the result I'm looking for is:
SN Date Value1 Value2 Value3
1234 2018-02-12 Hello 1111 Apples
1324 2018-02-12 There 2222 Pears
2134 2018-02-13 Baby 3333 Bananas
The query I ran is obviously wrong because I'm getting mostly NULL and only Value data, but here it is anyway:
SELECT SN,Date,Value1,Value2,Value3
FROM(
SELECT TableA.SN,
TableA.Date,
TableB.Name,
TableB.String,
TableB.Number
FROM TableA,TableB
WHERE
TableA.OpsID = TableB.OpsID
ORDER BY Date ASC
)Temp
PIVOT(
MAX(Value)
FOR Name in(
Value1,Value2,Value3
)
)PIV
Note that Value1 and Value3 are always VARCHAR and Value2 is always an INT
You combine String and Number into a single column in a subquery, and then pivot the values back out into their own columns like this:
SELECT SN, Date, Value1, CAST(Value2 AS INT) Value2, Value3
FROM
(
SELECT a.SN, a.Date, B.Name, ISNULL(b.String, CAST(b.Number AS VARCHAR(10))) Value
FROM TableA A
INNER JOIN TableB B ON A.OpsID = B.OpsID
)sq1
PIVOT (MAX(Value) FOR Name IN ([Value1], [Value2], [Value3]))sq2
You can do conditional aggregation :
select a.SN, a.date,
max(case when b.Name = 'Value1' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value1,
max(case when b.Name = 'Value2' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value2,
max(case when b.Name = 'Value3' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value3
from tablea a inner join
tableb b
on b.OpsID = a.OpsID
group by a.SN, a.date;
I need to build a SQL query in SQL SERVER 10.50.1600.1. I have the following model situation:
id1 | value1
id1 | value2
id2 | value1
id3 | value1
id3 | value2
...
and would like to end up in a situation as
id1 | value1 | value2
id2 | value1 | null
id3 | value1 | value2
...
I only know that for each id[n] there are at most 4 values recorded.
EDIT: I know there are at most 4 values for each, but they could be anything. They can be any number included in [0, 9000] or a string (about 10 possibilities). My bad, I didn't explain well.
If you know the values in advance, and the values are unique per ID (as they seem to be from your question statement) it's fairly straightforward:
-- Setup
declare #a table (id nvarchar(50), value nvarchar(50))
insert #a(id, value) values
('id1', 'value1'),
('id1', 'value2'),
('id2', 'value1'),
('id3', 'value1'),
('id3', 'value2')
;
SELECT id,
MAX(CASE value WHEN 'value1' THEN value END) AS value1,
MAX(CASE value WHEN 'value2' THEN value END) AS value2,
MAX(CASE value WHEN 'value3' THEN value END) AS value3,
MAX(CASE value WHEN 'value4' THEN value END) AS value4
FROM #a
GROUP BY id
Below query will help you :-
declare #test table (id nvarchar(50), value nvarchar(50))
insert #test(id, value) values
('id1', 'value1'),
('id1', 'value2'),
('id1', 'value3'),
('id1', 'value4'),
('id2', 'value1'),
('id3', 'value1'),
('id3', 'value2'),
('id3', 'value3');
select ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS ROWNUM,id,value into #t1 from #test
SELECT distinct id,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=1) AS Value1,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=2) AS Value2,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=3) AS Value3,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=4) AS Value4
FROM #t1 a
drop table #t1
Output :-
id Value1 Value2 Value3 Value4
id1 value1 value2 value3 value4
id2 value1 NULL NULL NULL
id3 value1 value2 value3 NULL
Assumtion: TABLE: table_name(id_column, value_column). With each value of id_column there are at most 4 values of value_column
Then you could use this
WITH tmp as
(SELECT
*
,ROW_NUMBER() over (PARTITION BY id_column order by value_column) rwn
FROM
table_name
)
SELECT
id_column
,MAX(CASE WHEN rwn = 1 THEN value_column END) value1
,MAX(CASE WHEN rwn = 2 THEN value_column END) value2
,MAX(CASE WHEN rwn = 3 THEN value_column END) value3
,MAX(CASE WHEN rwn = 4 THEN value_column END) value4
FROM
tmp
GROUP BY
id_column;
This question already has an answer here:
SQL transpose full table
(1 answer)
Closed 9 years ago.
Hello I am new to SQL and would really appreciate some help with transposing a table as follows. Looking at similar posts it seems that this may be accomplished with pivot/unpivot, but I am not sure since the examples I read about have much fewer columns. Any suggestions would be great!
Table.
CATEGORY Value1 Value2 Value3 Value4 ... Value15
Hot 18 17 9 17 ... 18
Warm 5 3 0 1 ... 3
Cold 20 2 1 2 ... 2
Desired Result.
CATEGORY Hot Warm Cold
Value1 18 5 20
Value2 17 3 2
Value3 9 0 1
Value4 17 1 2
… … … …
Value15 18 3 2
select *
from tbl
unpivot (value for name in (Value1, Value2, Value3, Value4, ... Value15)) unpiv
pivot (max(value) for category in ([hot],[warm],[cold])) piv
The following is a simple code i tried out. Just run and see if it meets your requirement!!
declare #Tbl1 table(Category Varchar(10), Value1 Int, Value2 Int, Value3 Int, Value4 Int, Value5 Int)
insert into #Tbl1(Category, Value1, Value2, Value3, Value4, Value5)
Values ('Hot', 12, 23, 43, 5, 6)
insert into #Tbl1(Category, Value1, Value2, Value3, Value4, Value5)
Values ('Warm', 41, 28, 4, 45, 16)
insert into #Tbl1(Category, Value1, Value2, Value3, Value4, Value5)
Values ('Cold', 1, 3, 543, 15, 26)
select * from #Tbl1
Declare #TblUP Table(Category Varchar(100), Value Int, [Types] Varchar(10))
Insert into #TblUP(Category, Value, Types)
select * from #Tbl1 unpivot ([values] for Types in (Value1, Value2, Value3, Value4, Value5)) as UNPIV
select * from #TblUP
Select Types, Hot, Warm, Cold
From
(Select Types, Category, Value from #TblUP) as TUP
PIVOT (SUM(Value) for [Category] in ([Hot], [Warm], [Cold]))
as PT
I have the following row from a table in MSSQL
Person | value1 | value2 | value3 | value4
John | 4 | 7 | 1 | 2
I want this row sorted according to the values as shown below.
Person | value2 | value1 | value4 | value3
John | 7 | 4 | 2 | 1
May be I'm asking a stupid question , I want the column names to be sorted according to the values in those column.
I know that this can be achieved using query
SELECT *
FROM tableName
ORDER BY value2, value1, value4, value3 DESC
But when I change the any column value, I have to change the query to get the result sorted.
Please help...
-- sample data
declare #t table
(
person varchar(50),
value1 int,
value2 int,
value3 int,
value4 int
)
insert into #t select 'John', 4, 7, 1, 2
insert into #t select 'Name1', 14, 7, 1, 16
insert into #t select 'Name2', 24, 8, 1, 2
-- query
select
person, v1 = [1], v2 = [2], v3 = [3], v4 = [4]
from
(
select person, rn = row_number() over(partition by person order by a desc), a
from #t t1
unpivot
(
a for b in (value1, value2, value3, value4)
) t2
) t1
pivot
(
max(a) for rn in ([1], [2], [3], [4])
) t2
unless I'm missing something, you should just append 'order by person, value2, value1, value4, value3' at the end of your select statement.
I think you want:
SELECT Person, Value2, Value1, Value4, Valuer
FROM YourTable
try this:
SELECT * FROM tableName ORDER BY value2, value1, value4, value3 DESC