I need to take data from a table that looks like this:
name | server | instance | version | user
----------|----------|------------|----------|--------- -
package_a | x | 1 | 1 | AB
package_b | x | 1 | 1 | TL
package_a | x | 2 | 4 | SK
package_a | y | 1 | 2 | MD
package_c | y | 1 | 4 | SK
package_b | y | 2 | 1 | SK
package_a | y | 2 | 1 | TL
package_b | x | 2 | 3 | TL
package_c | x | 2 | 1 | TL
and I need to put it in a table like that:
name | v_x_1 | u_x_1 | v_x_2 | u_x_2 | v_y_1 | u_y_1 | v_y_2 | u_y_2
----------|-------|-------|-------|-------|-------|-------|-------|-------
package_a | 1 | AB | 4 | SK | 2 | MD | 1 | TL
package_b | 1 | TL | 3 | TL | NULL | NULL | 1 | SK
package_c | NULL | NULL | 1 | TL | 4 | SK | NULL | NULL
I already tried INSERT with (SUB)SELECT, tried to INSERT package names first using DISTINCT and UPDATE afterwards, played around with PIVOT and stuff like that.
But I'm rather new to SQL and programming in general, so I couldn't come up with a solution. Since I not only have a version number in the source table but also nvarchar columns, It seems like PIVOT won't be the way to go, right?
You can use PIVOT on a sub query that uses UNION to separate the user and version values.
insert into YourNewTable (name, [v_x_1],[u_x_1],[v_x_2],[u_x_2],[v_y_1],[u_y_1],[v_y_2],[u_y_2])
select *
from (
select name, cast([version] as varchar(30)) as value, concat('v_',[server],'_',instance) as title from YourTable
union all
select name, [user] as value, concat('u_',[server],'_',instance) as title from YourTable
) q
pivot (max(value) FOR title IN (
[v_x_1],[u_x_1],[v_x_2],[u_x_2],[v_y_1],[u_y_1],[v_y_2],[u_y_2]
)
) pvt;
Related
This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 1 year ago.
What I want to do is to set column Deleted = 1 for all duplicates in table Customers except of one. So that one entry remains.
Table:
| Deleted | ID | Number | Name |
-----------------------------------
| 0 | 2A3E | 100004 | Andy |
| 0 | 9P3W | 102506 | Judy |
| 0 | 3R4Z | 120097 | Freddy|
| 0 | 1G5Y | 103905 | Nikky |
| 0 | 2A3E | 103905 | Nikky |
| 0 | 9P3W | 147001 | Johnny|
| 0 | 5K7V | 120097 | Teddy |
| 0 | 6D8S | 120097 | Teddy |
Query:
WITH DataSource AS
(
SELECT *,
COUNT(*) OVER (PARTITION BY Number) count_calc
FROM Customers
)
SELECT *
FROM DataSource
WHERE count_calc > 1
Results:
| Deleted | ID | Number | Name |
-----------------------------------
| 0 | 1G5Y | 103905 | Nikky |
| 0 | 2A3E | 103905 | Nikky |
| 0 | 5K7V | 120097 | Teddy |
| 0 | 6D8S | 120097 | Teddy |
Now I want set Deleted = 1 for only one Nikky and one Teddy.
Tried DISTINCT and GROUP BY but didn't work. How can I modify the query so that it returns only one of these duplicates from Nikky and Teddy and not both? But at the same time returns all columns so that I can set Deleted of one to 1?
You are part-way there, you need to use row_number over a window, then you can use an updatable CTE:
with d as (
select * , Row_Number() over(partition by number order by id) rn
from customers
)
update d set deleted=1 where rn>1
I have a SQL Server 2016 temp table that looks like this:
SECTION_NAME SORT_ORDER COL1 COL2 COL3 COL4 COL5 COL6 COL7 COL8 COL9 COL10
ONE 1 A B C D E F G H I J
ONE 2 C D E F G H I X Y Z
I am only selecting the COL columns and want each records COL columns to be on a separate row, like this:
SELECT * FROM #TEMPTABLE
A
B
C
D
E
etc
How can I do that? I don't know PIVOT very well so not sure if I can use that. Thanks!
You need to "unpivot" which I prefer to do using cross apply and values, like this
SELECT
row_number() over (order by SECTION_NAME, SORT_ORDER, ca.value) as ID
, section_name
, sort_order
, ca.value
FROM pivoted
CROSS APPLY (
VALUES
(col1)
, (col2)
, (col3)
, (col4)
, (col5)
, (col6)
, (col7)
, (col8)
, (col9)
, (col10)
) AS ca(value)
which produces:
+----+--------------+------------+-------+
| ID | section_name | sort_order | value |
+----+--------------+------------+-------+
| 1 | ONE | 1 | A |
| 2 | ONE | 1 | B |
| 3 | ONE | 1 | C |
| 4 | ONE | 1 | D |
| 5 | ONE | 1 | E |
| 6 | ONE | 1 | F |
| 7 | ONE | 1 | G |
| 8 | ONE | 1 | H |
| 9 | ONE | 1 | I |
| 10 | ONE | 1 | J |
| 11 | ONE | 2 | C |
| 12 | ONE | 2 | D |
| 13 | ONE | 2 | E |
| 14 | ONE | 2 | F |
| 15 | ONE | 2 | G |
| 16 | ONE | 2 | H |
| 17 | ONE | 2 | I |
| 18 | ONE | 2 | X |
| 19 | ONE | 2 | Y |
| 20 | ONE | 2 | Z |
+----+--------------+------------+-------+
see this demo
This is a bit of a tricky question/situation and my search fu failed me.
Lets say i have the following data
| UID | SharedID | Type | Date |
|-----|----------|------|-----------|
| 1 | 1 | foo | 2/4/2016 |
| 2 | 1 | foo | 2/5/2016 |
| 3 | 1 | foo | 2/8/2016 |
| 4 | 1 | foo | 2/11/2016 |
| 5 | 2 | bar | 1/11/2016 |
| 6 | 2 | bar | 2/11/2016 |
| 7 | 3 | baz | 2/1/2016 |
| 8 | 3 | baz | 2/3/2016 |
| 9 | 3 | baz | 2/11/2016 |
And I would like to ommit a variable number of leading rows (most recent date in this case) and lets say that number is 2 in this example. The resulting table would be something like this:
| UID | SharedID | Type | Date |
|-----|----------|------|-----------|
| 1 | 1 | foo | 2/4/2016 |
| 2 | 1 | foo | 2/5/2016 |
| 7 | 3 | baz | 2/1/2016 |
Is this possible in SQL? Essentially I want to filter on an unknown number of rows which uses the date column as the order by. The goal is to get the oldest types and get a list of UID's in the process.
Sure, it's possible. Use a ROW_NUMBER function to assign a value to each row, partitioning by the SharedID column so that the count restarts every time that ID changes, and select those rows with a value greater than your limit.
WITH cteNumberedRows AS (
SELECT UID, SharedID, Type, Date,
ROW_NUMBER() OVER(PARTITION BY SharedID ORDER BY Date DESC) AS RowNum
FROM YourTable
)
SELECT UID, SharedID, Type, Date
FROM cteNumberedRows
WHERE RowNum > 2;
Not sure if I understand what you mean but something like this?
SELECT * FROM MyTable t1 JOIN MyTable T2 ON t2.id NOT IN (
SELECT TOP 2 UID FROM myTable
WHERE SharedID = t1.sharedID
ORDER BY [Date] DESC
)
I would like to update a table:
| id | type_id | created_at | sequence |
|----|---------|------------|----------|
| 1 | 1 | 2010-04-26 | NULL |
| 2 | 1 | 2010-04-27 | NULL |
| 3 | 2 | 2010-04-28 | NULL |
| 4 | 3 | 2010-04-28 | NULL |
To this (note that created_at is used for ordering, and sequence is "grouped" by type_id):
| id | type_id | created_at | sequence |
|----|---------|------------|----------|
| 1 | 1 | 2010-04-26 | 1 |
| 2 | 1 | 2010-04-27 | 2 |
| 3 | 2 | 2010-04-28 | 1 |
| 4 | 3 | 2010-04-28 | 1 |
Same question has been raised but for SQL Server.
Link
Thanks.
You can use ROW_NUMBER() to get sequence number per type_id slice. Use a CTE to make UPDATE operation simpler:
;WITH ToUpdate AS (
SELECT id, type_id, created_at, sequence,
ROW_NUMBER() OVER (PARTITION BY type_id ORDER BY created_at) AS newSeq
FROM mytable
)
UPDATE ToUpdate
SET sequence = newSeq
Demo here
being a novice sql user:
I have a simple table storing some records over night daily. table:
Table: T1
+----+-----+----+-----------+------------+
| Id | A | AB | Value | Date |
+----+-----+----+-----------+------------+
| 1 | abc | I | -48936.08 | 2013-06-24 |
| 2 | def | A | 431266.19 | 2013-06-24 |
| 3 | xyz | I | -13523.90 | 2013-06-24 |
| 4 | abc | A | 13523.90 | 2013-06-23 |
| 5 | xyz | I | -13523.90 | 2013-06-23 |
| 6 | def | A | 13523.90 | 2013-06-22 |
| 7 | def | I | -13523.90 | 2013-06-22 |
+----+-----+----+-----------+------------+
I would like to get all values of columns A,AB, Value for the latest Date on Column A filtered on AB = I
basically the result should look like:
+----+-----+----+-----------+------------+
| Id | A | AB | Value | Date |
+----+-----+----+-----------+------------+
| 1 | abc | I | -48936.08 | 2013-06-24 |
| 3 | xyz | I | -13523.90 | 2013-06-24 |
| 7 | def | I | -13523.90 | 2013-06-22 |
+----+-----+----+-----------+------------+
I have tried to use inner join twice on the same table but failed to come up with correct result.
any help would be appreciated.
thanks :)
This will work with sqlserver 2005+
;WITH a as
(
SELECT id, A,AB, Value, Date
, row_number() over (partition by A order by Date desc) rn
FROM t1
WHERE AB = 'I'
)
SELECT id, A,AB, Value, Date
FROM a WHERE rn = 1
; WITH x AS (
SELECT id
, a
, ab
, "value"
, "date"
, Row_Number() OVER (PARTITION BY a ORDER BY "date" DESC) As row_num
FROM your_table
WHERE ab = 'I'
)
SELECT *
FROM x
WHERE row_num = 1