SQL query transposing columns - sql

I have a table in the following structure:
id | att1 | att2 | att3
-----------------------
1 | a1 | b1 | c1
2 | a2 | b2 | c2
3 | a3 | b3 | c3
And I want to transpose the columns to become rows for each id. Like this:
id | attname | value
------------------------
1 | att1 | a1
1 | att2 | b1
1 | att3 | c1
2 | att1 | a2
2 | att2 | b2
2 | att3 | c2
3 | att1 | a3
3 | att2 | b3
3 | att3 | c3
I was reading up on the PIVOT function and wasn't sure if it would do the job or how to use it. Any help would be appreciated.

You can use unpivot for this task.
SELECT *
FROM table
UNPIVOT (
value FOR att_name
IN (att1 as 'att1', att2 as 'att2', att3 as 'att3')
);

Here is another method :
SELECT id,attname, value
FROM Yourtable
CROSS APPLY ( VALUES ('att1',att1), ('att2',att2), ('att3',att3)) t(attname, value)

Do UNION ALL:
select id, 'att1' as attname, att1 as value from tablename
union all
select id, 'att2' as attname, att2 as value from tablename
union all
select id, 'att3' as attname, att3 as value from tablename
Note that VALUE is a reserved word in SQL, so if that's your real column name you need to double quote it, "value".

Related

Oracle SQL Transforming sql rows into columns grouping by another column

I am facing trouble designing SQL for the below scenario.
My table structure looks like this
TABLE IMSK
id | key | value | group_id
1 | k1 | a1 | g1
2 | k2 | a2 | g1
3 | k3 | a3 | g1
4 | k1 | b1 | g2
5 | k2 | b2 | g2
6 | k3 | b3 | g2
As you can see, I store 3 keys for every group id. Values will be different for each group_id. I need to show this information in a report in the following manner.
k1 | k2 | k3
a1 | a2 | a3
b1 | b2 | b3
Keys will become the column headers and every row will correspond to a group_id
One method is conditional aggregation:
select group_id,
max(case when key = 'k1' then value end) as key1,
max(case when key = 'k2' then value end) as key2,
max(case when key = 'k3' then value end) as key3
from imsk
group by group_id;
Using Pivot
Demo
WITH CTE1 AS(
SELECT KEY, VALUE FROM TABLE1)
SELECT * FROM CTE1
PIVOT (MAX(VALUE) FOR KEY IN ('k1', 'k2', 'k3'))
UNION
SELECT * FROM CTE1
PIVOT (MIN(VALUE) FOR KEY IN ('k1', 'k2', 'k3'));

How can I transform a column containing some strings into multi columns using postgresql?

I have the following table (the data type of the column value is varchar, some values such as c2 and c4 are missing) :
__________________________
id | value
__________________________
1 | {{a1,b1,c1},{a2,b2,}}
__________________________
2 | {{a3,b3,c3},{a4,b4}}
__________________________
and I would like to obtain something like:
id | A | B | C
__________________
1 | a1 | b1 | c1
__________________
1 | a2 | b2 |
__________________
2 | a3 | b3 | c3
__________________
2 | a4 | b4 |
I am trying to use regexp_split_to_array, without any success so far.
How can this be achieved?
Thank you!
This assumes you know what the possible values are (e.g. a*, b*) because otherwise generating the appropriate columns for the value types will require dynamic sql.
Setup:
CREATE TABLE t (id INTEGER, value VARCHAR);
INSERT INTO t
VALUES
(1, '{{a1,b1,c1},{a2,b2,}}'),
(2, '{{a3,b3,c3},{a4,b4}}')
;
Query:
SELECT
id,
NULLIF(r[1], '') AS a,
NULLIF(r[2], '') AS b,
NULLIF(r[3], '') AS c
FROM (
SELECT id, regexp_split_to_array(r[1], ',') AS r
FROM (
SELECT id, regexp_matches(value, '{([^{][^}]+)}', 'g') AS r
FROM t
) x
) x;
Result:
| id | a | b | c |
| --- | --- | --- | --- |
| 1 | a1 | b1 | c1 |
| 1 | a2 | b2 | |
| 2 | a3 | b3 | c3 |
| 2 | a4 | b4 | |
Note that if it's possible for earlier values to be missing, e.g. {b1,c1} where a1 is missing, then the query would have to be different.
You can use string_to_array to convert string to array and then explode it in multiple rows with unnest:
EXAMPLE
SELECT unnest(string_to_array('{1 2 3},{4 5 6},{7 8 9}', ','));
{1 2 3}
{4 5 6}
{7 8 9}

Impala pivot from column to row, column names disappear

I am kind of new to impala, and to sql in general. I am trying to do some pivot operations in order to start with this table.
Input:
Name table: MyName
+-----------+---------------------+-----------+
| Column A  | Column B | Column C |
+-----------+---------------------+-----------+
| a1 | b1 | c1 |
| a2 | b2 | c2 |
| a3 | b3 | c3 |
+-----------+---------------------+-----------+
And to obtain this other table trasposed, where b1, b2, b3 goes from column to row.
output:
+-----------+---------------------+-----------+
| b1   | b2 | b3 |
+-----------+---------------------+-----------+
| a1 | a2 | a3 |
| c1 | c2 | c3 |
+-----------+---------------------+-----------+
This is the code I came up so far:
select b_column,
max(case where b_column='b%' then column_a, column_c end) column_a, column_c
from MyName
group by b_column;
But it's not working and I am feeling pretty stuck.
Can anyone give me a hint/suggestion on how to solve the issue?
Thanks so much in advance!
If you are trying to do a pivot in imapla in general, you can't per the 6.1 documentation, PIVOT is not a current functionality.
https://www.cloudera.com/documentation/enterprise/6/6.1/topics/impala_reserved_words.html
select b_column,
max(case when b_column like 'b%' then column_a end) column_a,
max(case when b_column like 'c%' then column_c end) column_c
from MyName
group by b_column;

How to make 2 columns from one in one select in sqlite?

I've got one database with two columns (id and value). There are two types of values and each id has both of this values. How can I make a select to this database to have three columns in result (id, value1 and value2)
I've tried CASE and GROUP BY, but it shows only one result of each id
Example of a db:
| id | value |
| 0 | a |
| 0 | b |
| 1 | a |
| 1 | b |
Example of the result I am looking for is:
| id | value_a | value_b |
| 0 | a | b |
| 1 | a | b |
UPDATE:
As it was noted in comments, there is too simple data in the example.
The problem is more complicated
An example that would better describe it:
DB:
| id | value | value2 | value3 |
| 0 | a | a2 | a3 |
| 0 | b | b2 | b3 |
| 1 | a | c2 | c3 |
| 1 | b | d2 | d3 |
RESULT:
| id | value_a | value_b | value2_a | value2_b | value3_a | value3_b |
| 0 | a | b | a2 | b2 | a3 | b3 |
| 1 | a | b | c2 | d2 | c3 | d3 |
The output should be sorted by id an have all info from the both rows of each id.
If there are always two values per ID, you can try an aggregation using min() and max().
SELECT id,
min(value) value_a,
max(value) value_b
FROM elbat
GROUP BY id;
select t0.id,t0.Value as Value_A, t1.Value as Value_B
from test t0
inner join test t1 on t0.id = t1.id
where t0.Value = 'a' and t1.value = 'b';
I have used this method to turn "rows" into "columns". Depending on the number of unique values that exist in the table, you may or may not want to use this :)
SELECT id, SUM(CASE WHEN value = "a" then 1 else 0 END) value_a,
SUM(CASE WHEN value = "b" then 1 else 0 END) value_b,
SUM(CASE WHEN value = "c" then 1 else 0 END) value_c,
SUM(CASE WHEN value ="a2" then 1 else 0 END) value_a2,
.
.
.
FROM table
GROUP BY id;
Thanks all for the answers! This is the way how I did this:
WITH a_table AS
(
SELECT id, value, value2, value3 FROM table1 WHERE table1.value = 0
),
b_table AS
(
SELECT id, value, value2, value3 FROM table1 WHERE table1.value = 1
)
SELECT DISTINCT
a_table.id AS id,
a_table.value AS value_a,
a_table.value2 AS value2_a,
a_table.value3 AS value3_a,
b_table.value AS value_b,
b_table.value2 AS value2_b,
b_table.value3 AS value3_b
FROM a_table
JOIN b_table ON a_table.id = b_table.id
GROUP BY id;

Sql Server get first matching value

I have two tables History and Historyvalues:
History
HID(uniqeidentifier) | Version(int)
a1 | 1
a2 | 2
a3 | 3
a4 | 4
Historyvalues
HVID(uniqeidentifier) | HID(uniqeidentifier) | ControlID(uniqeidentifier) | Value(string)
b1 | a1 | c1 | value1
b2 | a2 | c1 | value2
b3 | a2 | c2 | value3
Now I Need a query where I can get a list with the last historyvalue of each control from a specific Version like:
Get the last values from Version 3 -> receiving ->
HVID | ControlID | Value
b2 | c1 | value2
b3 | c2 | value3
I tried something like this:
Select HVID, ControlId, max(Version), Value from
(
Select HVID, ControlId, Version, Value
from History inner JOIN
Historyvalues ON History.HID = Historyvalues.HID
where Version <= 3
) as a
group by ControlId
order by Version desc
but this does not work.
Are there any ideas?
Thank you very much for your help.
Best regards
Latest version from each control with your specific Version (WHERE t1.Version <= 3)
Query:
SQLFIDDLEExample
SELECT HVID, ControlId, Version, Value
FROM
(
SELECT t2.HVID, t2.ControlId, t1.Version, t2.Value,
ROW_NUMBER() OVER(PARTITION BY t2.ControlId ORDER BY t1.Version DESC) as rnk
FROM History t1
JOIN Historyvalues t2
ON t1.HID = t2.HID
WHERE t1.Version <= 3
) AS a
WHERE a.rnk = 1
ORDER BY a.Version desc
Result:
| HVID | CONTROLID | VERSION | VALUE |
|------|-----------|---------|--------|
| b2 | c1 | 2 | value2 |
| b3 | c2 | 2 | value3 |
here is your solution
Select Historyvalues.HVID,Historyvalues.ControlID,Historyvalues.Value
from Historyvalues
inner join History on Historyvalues.hid=History.hid
where Historyvalues.hvid in (
select MAX(Historyvalues.hvid) from Historyvalues
inner join History on Historyvalues.hid=History.hid
group by ControlID)