We have this table:
Column A
Column B
01-01-2020
23
01-01-2020
24
01-01-2020
25
02-01-2020
11
02-01-2020
15
The requirement is to load the data in single row based on datetime column.
Column A
Column B
Column C
Column D
01-01-2020
23
24
25
02-01-2020
11
15
There can be up to 200 unique values against single datetime value.
How can this be achieved in a query?
I have tried using pivot but that results is aggregation which is not what I am after.
Since you have up to 200 hundred columns, I figured it would be best to number them. You can expand up to the required number of columns
Example
Select *
From (
Select [Column A]
,[Column B]
,RN = row_number() over (partition by [Column A] order by [Column B] )
From YourTable
) src
Pivot ( max([Column B]) for RN in ( [1], [2], [3], [4], [5], [6], [7], [8], [9],[10]
,[11],[12],[13],[14],[15],[16],[17],[18],[19],[20]
,[21],[22],[23],[24],[25],[26],[27],[28],[29],[30]
) ) Pvt
Related
Raw data:
ID Age Date Value
-------------------------
1 5 01/01/2023 10
1 5 01/04/2023 15
2 7 01/02/2023 17
3 9 10/02/2022 7
3 9 12/20/2022 9
Desired output:
One ID/Age per row (Age will always be the same per ID)
Use latest Date partitioned by ID if has multiple dates
Pivot the Value column into two separate columns, Value_1 and Value_2
If an ID does not have 2nd value, in the output, leave Value_2 blank
Value_1 is the highest, Value_2 is second highest
This is what the output should look like:
ID Age Date Value_1 Value_2
-------------------------------------
1 5 01/04/2023 15 10
2 7 01/02/2023 17
3 9 12/20/2022 9 7
I couldn't figure it out even after reading the PIVOT reference. It is little bit different than the example I read over. The column I am pivoting is a numeric column, not categorical. I need some help here.
https://www.techonthenet.com/sql_server/pivot.php
My attempt/some ideas:
select *
from
(select
ID, Age, Date,
Value,
row_number() over (partition by ID order by Date desc) row_num
from
table) a
where
a.row_num = 1
SELECT
ID, Age, Date, 'Value_1', 'Value_2'
FROM
(SELECT
ID, Age, Date, Value
FROM
table) AS SourceTable
PIVOT
(SUM(Value)
FOR Date IN ('day1', 'day2')
) AS PivotTable;
Updates: both #dale-k and #t-n's solution are good. If you have more than 2 values you can try #t-n's PIVOT approach. Thanks for your help!
The following query returns your desired results using standard aggregation with a case expression.
select
ID
, Age
, max([Date]) [Date]
, max([Value]) Value_1
, case when min([Value]) <> max([Value]) then min([Value]) else null end Value_2
from #MyTable
group by ID, Age;
Returns:
ID
Age
Date
Value_1
Value_2
1
5
2023-01-04
15
10
2
7
2023-01-02
17
NULL
3
9
2022-12-20
9
7
For a solution that uses ROW_NUMBER() and PIVOT and can be expanded to more than two Value columns, try:
SELECT PVT.ID, PVT.Age, PVT.Date,
[1] AS Value_1, [2] AS Value_2
FROM (
SELECT
ID, Age, Value,
MAX(Date) OVER(PARTITION BY ID, Age) AS Date,
ROW_NUMBER() OVER(PARTITION BY ID, Age ORDER BY Value DESC) AS RN
FROM #Data D
) Source
PIVOT (
MAX(Source.Value)
FOR Source.RN IN ([1], [2])
) PVT
ORDER BY PVT.ID, PVT.Age
See this db<>fiddle.
This is my original table:
Original table
And I would like it to be as:
CityID | 1 | 2 | 3 | 4 | 5 | 6 | 7
_____________________________________
1024 0800 0900 and so on...
Here is my code, but I get a syntax error near FOR.
select * from
(select SIDURI as CityID, DAY as ArrivalDay, T_FROM as TimeArrival
from RNFIL488) as timingTable
pivot(
timing.SIDURI as CityID
timingTable.T_FROM as TimeArrival
for timing.DAY as ArrivalDay in (
[1],
[2],
[3],
[4],
[5],
[6],
[7]
)
) as pivot_table
Use ROW_NUMBER here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY CityID ORDER BY ArrivalDay) rn
FROM RNFIL488
)
SELECT
CityID,
MAX(CASE WHEN rn = 1 THEN TimeArrival END) AS [1],
MAX(CASE WHEN rn = 2 THEN TimeArrival END) AS [2],
MAX(CASE WHEN rn = 3 THEN TimeArrival END) AS [3],
MAX(CASE WHEN rn = 4 THEN TimeArrival END) AS [4],
MAX(CASE WHEN rn = 5 THEN TimeArrival END) AS [5],
MAX(CASE WHEN rn = 6 THEN TimeArrival END) AS [6],
MAX(CASE WHEN rn = 7 THEN TimeArrival END) AS [7]
FROM cte
GROUP BY
CityID;
This assumes that your original source table would always have 7 arrival days per city. If not, then we might have to use a calendar table to bring in the missing data. Also, I am avoiding the PIVOT operator, because often the above approach performs better (and I also find it much easier to read).
I recommend if you don't have a lot data then you can truncate the table and re-fill table. And don't forget your id column should be unique and use auto_increment on id.
I have a dataset in SQL server management studio 17 that requires some pivoting to collapse multiple rows into one row for ease of reading and saving space. Per unique id there are a set of codes which act as operators on the values, with the intention of displaying the results in a total column at the end. I've performed a primary pivot with one set of codes, but it looks like I need to do a second one to do further collapsing/amalgamation.
Here is some unpivoted data
PO_NUM u_id CODE_1 CODE_2 VALUE
---------------------------------------
0M274316 1 3 9;13 150
0N274316 1 9 9 200000
0O274316 1 6 9 210000
0P274316 1 6 13 21000
0Q274316 1 6 9 50000.5
0R274316 1 15 9 0
0M274317 2 3 9;13 150
0N274317 2 9 9 300000
0O274317 2 6 9 220000
0P274317 2 6 13 22000
0Q274317 2 6 8 90000.5
0R274317 2 15 8 0
With a sample pivot with the first unique id as an example I get:
PO_NUM uid CODE_1 CODE_2 6 9 15
-----------------------------------------------------
0M274316 1 3 9;13 210000 200000 0
0M274316 1 9 21000 NULL NULL
0M274316 1 13 50000.5 NULL NULL
What I need to do is another pivot to have '9;13' as columns with sums being used with the values. I have this initial pivot command as:
SELECT PO_NUM, CODE_1, CODE_2, VALUE from table
Pivot (max(VALUE) for CODE_2 in ([6],[9],[15])) pvt1
Which merges the data as expected when I don't include the CODE_1 vals. But trying to add the second pivot with CODE_2 just further messes the data. How do I pivot a second time using the pivoted data from the first command?
Expected output would be:
PO_NUM uid 6 9 15 9;13 9(2) 13 total
------------------------------------------------------------------------
0M274316 1 281000.5 200000 0 150 null null 481150.5
Basically they rows have been collapsed into one with the codes being broken out into columns. In reality the columns will be renamed to avoid conflicts with names, therefore I used 9(2) just to show the data is still there.
Sorry about the edits.
If I understand correctly, just use conditional aggregation:
select po_num, u_id, code_2,
max(case when code_1 = 3 then value end) as [3],
max(case when code_1 = 6 then value end) as [6],
max(case when code_1 = 9 then value end) as [9],
max(case when code_1 = 15 then value end) as [15]
from t
group by po_num, u_id, code_2;
I think this would be expressed using pivot as:
SELECT PO_NUM, u_id, CODE_2, [3], [6], [9], [15]
from table
Pivot (max(VALUE) for CODE_2 in ([3], [6], [9], [15])) pvt1;
You can try this.
DECLARE #MyTable TABLE(PO_NUM VARCHAR(10), u_id int, CODE_1 varchar(10), CODE_2 varchar(10), VALUE DECIMAL(18,2))
INSERT INTO #MyTable VALUES
('0M274316', 1, '3', '9;13', 150),
('0N274316', 1, '9', '9', 200000),
('0O274316', 1, '6', '9', 210000),
('0P274316', 1, '6', '13', 21000),
('0Q274316', 1, '6', '9', 50000.5),
('0R274316', 1, '15', '9', 0),
('0M274317', 2, '3', '9;13', 150),
('0N274317', 2, '9', '9', 300000),
('0O274317', 2, '6', '9', 220000),
('0P274317', 2, '6', '13', 22000),
('0Q274317', 2, '6', '8', 90000.5),
('0R274317', 2, '15', '8', 0)
SELECT *, [6] + [9] + [15] + [9;13] + [9(2)] + [13] as total FROM (
SELECT PO_NUM,u_id, CODE + ( CASE WHEN DENSE_RANK() OVER( PARTITION BY CODE ORDER BY C ) > 1 THEN '(' + CAST ( C AS varchar(50)) + ')' ELSE '' END ) CODE, VALUE
FROM (
SELECT MIN(PO_NUM) OVER(PARTITION BY u_id) PO_NUM, u_id, 1 C, CODE_1 CODE, VALUE FROM #MyTable
UNION ALL
SELECT MIN(PO_NUM) OVER(PARTITION BY u_id) PO_NUM, u_id, 2 C, CODE_2 CODE, VALUE from #MyTable
) T
) SRC
PIVOT(SUM(VALUE) FOR CODE IN ( [6], [9], [15], [9;13], [9(2)], [13])) PVT
Result:
PO_NUM u_id 6 9 15 9;13 9(2) 13 total
---------- ----------- ------------ ----------- --------- --------- ----------- ----------- -------------
0M274316 1 281000.50 200000.00 0.00 150.00 460000.50 21000.00 962151.00
0M274317 2 332000.50 300000.00 0.00 150.00 520000.00 22000.00 1174150.50
I need to transform, transpose, whatever the right terminology is a data set with multiple rows and instead return a single row with multiple columns. Here is a sample of the data that I start with
EID PM Project HOURS WeekStarting
joe#test.com tom#test.com Proj A 6 11/28/2016
joe#test.com tom#test.com Proj A 3 12/5/2016
joe#test.com tom#test.com Proj A 7 12/12/2016
joe#test.com tom#test.com Proj A 3 12/19/2016
sue#test.com sam#test.com Proj B 3 11/28/2016
sue#test.com sam#test.com Proj B 6 12/12/2016
sue#test.com sam#test.com Proj B 7 12/19/2016
I would like to format the data like so
EID PM Project Week1 Week2 Week3 Week4
joe#test.com tom#test.com Proj A 6 3 7 3
sue#test.com sam#test.com Proj B 3 0 6 7
Note that for sue there is no data in week2 in my source data so the result is 0 for week 2.
Currently I am doing this in Javascript using the reduce function but it's very messy. I would rather try to fix the data and have clean Javascript.
Any help is much appreciated.
Declare #SQL varchar(max)
Select #SQL = Stuff((Select ','+QuoteName('Week'+cast(WeekNr as varchar(25)))
From (Select Distinct Top 100 Percent WeekNr=Dense_Rank() over (Order By WeekStarting) From YourTable
Order By 1) A
For XML Path ('')),1,1,'')
Select #SQL = 'Select EID,PM,Project,' + #SQL + '
From (
Select EID
,PM
,Project
,Item = ''Week''+cast(Dense_Rank() over (Order By WeekStarting) as varchar(25))
,Val = Hours
From YourTable
) A
Pivot (max(Val) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
You can query like this:
;with cte as (
select *, DATEPART(WEEK, weekstarting) -
DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM,0,weekstarting), 0)) + 1 AS WEEK_OF_MONTH
from yourtranspose
)
select Eid, PM, Project, [1], [2], [3], [4], [5] from
( select EID, PM, Project, WEEK_OF_MONTH , hours from cte ) a
pivot (max(hours) for week_of_month in ([1], [2], [3], [4], [5])) p
for each extra row you need to join the table against itself
I have TWO tables
1) column
2) row
COLUMN TABLE
COLumnID
----------------
1
2
3
4
5
6
7
8
9
ROW TABLE
ROW iD
-------------
100
104
101
99
77
20
10
The final output should look like this:
01.Row 1 2 3 4 5 6 7 8 9
02.----------- ---- ---- ---- ---- ---- ---- ---- ---- ----
03.10 x x x
04.20 x x x x
05.77 x x
06.99 x x x
07.100 x x x x
08.101 x
09.104 x x x x
The challenge is to mark a coordinate, with a value of X, if and only if the row value is divisible by the col value, i.e. it has a modulo of zero. The additional requirements are: the final query must work with random row values and the pivot operator should be used.
The following should do what you are looking for in sql server.
use a CTE to determine where the x should be and then pivot from that CTE
with mq as(select a.rowid
,b.columnid
,case when (a.rowid % b.columnid) = 0 then 'X' else null end as coord
from row_table a
inner join column_table b on 1=1)
select rowid,[1], [2], [3], [4],[5], [6], [7], [8], [9]
from mq
pivot( max(coord) for columnid in ([1], [2], [3], [4],[5], [6], [7], [8], [9])) as pv