SQL Subqueries as own column - sql

consider this. My Table looks something like this
ID1 | ID2 | Value |
1 1 Three
1 2 Random
1 3 Words
2 1 Not
2 2 So
2 3 Random
3 1 Why
3 2 No
3 3 Yes
And my output should look like
ID | Value1 | Value2 | Value3
1 | Three | Random | Words
2 | Not | So | Random
3 | Why | No | Yes
What am I looking for? I don't need a solution, just the concept to look for as I am lost. Thank you.

The concept you are looking for is PIVOT or TRANSPOSE. Try searching for "Convert Rows to Columns" in google.
In oracle, your PIVOT query would be as follows:
SELECT *
FROM (SELECT ID1 ID, VALUE
FROM MY_TABLE)
PIVOT (MIN(VALUE) AS VALUE FOR (ID2) IN ('1' ,'2','3'));
Here is a site for reference

Try this.
SQL QUERY
SELECT ID1 As 'ID',
MAX(IF(ID2=1 ,Value,null)) AS 'Value1',
MAX(IF(ID2=2,Value,null)) AS 'Value2',
MAX(IF(ID2=3,Value,null)) AS 'Value3'
FROM MyTable GROUP BY ID1;
OR
SELECT ID1 AS 'ID',
[1] AS 'Value1',
[2] AS 'Value2',
[3] AS 'Value3'
FROM (
SELECT ID1,ID2,Value
FROM MyTable) x
PIVOT(
MAX(Value)
FOR ID2 IN ([1],[2],[3])
) p
FIND SQL FIDDLE HERE

Related

How to get distinct count over multiple columns in Hive SQL?

I have a table that looks like this. And I want to get the distinct count horizontally across the three columns ignoring nulls.
ID
Column1
Column 2
Column 3
1
A
B
C
2
A
A
B
3
A
A
The desired output I'm looking for is:
ID
Column1
Column 2
Column 3
unique_count
1
A
B
C
3
2
A
A
B
2
3
A
A
1
One possible option would be
WITH sample AS (
SELECT 'A' Column1, 'B' Column2, 'C' Column3 UNION ALL
SELECT 'A', 'A', 'B' UNION ALL
SELECT 'A', 'A', NULL UNION ALL
SELECT '', 'A', NULL
)
SELECT Column1, Column2, Column3, COUNT(DISTINCT NULLIF(TRIM(c), '')) unique_count
FROM (SELECT *, ROW_NUMBER() OVER () rn FROM sample) t LATERAL VIEW EXPLODE(ARRAY(Column1, Column2, Column3)) tf AS c
GROUP BY Column1, Column2, Column3, rn;
output
+---------+---------+---------+--------------+
| column1 | column2 | column3 | unique_count |
+---------+---------+---------+--------------+
| | A | NULL | 1 |
| A | A | NULL | 1 |
| A | A | B | 2 |
| A | B | C | 3 |
+---------+---------+---------+--------------+
case when C1 not in (C2, C3) then 1 else 0 end +
case when C2 not in (C3) then 1 else 0 end + 1
This will not work if you intend to count nulls. The pattern would extend to more columns by successively comparing each one to all columns to its right. The order doesn't strictly matter. There's just no point in repeating the same test over and over.
If the values were alphabetically ordered then you could test only adjacent pairs to look for differences. While that applies to your limited sample it would not be the most general case.
Using a column pivot with a distinct count aggregate is likely to be a lot less efficient, less portable, and a lot less adaptable to a broad range of queries.

SQL - Combine data from several columns into one column

I am creating complicated CTE Query. In MSSQL
Which result will be something like that
| Id1 | Id2 | Id3 |
| 1 | 2 | 3 |
| 5 | 4 | 1 |
| 6 | 5 | 2 |
And now I need to combine all data into on column something like that
| Ids |
| 1 |
| 2 |
| 3 |
| 5 |
| 4 |
| 1 |
| 6 |
| 5 |
| 2 |
I want to try avoid union all and select by each column
Thanks
My favorite way of doing this uses cross apply:
select v.id
from t cross apply
(values (t.id1), (t.id2), (t.id3)) v(id);
Like the version using unpivot this only reads the table once. A version using union all would scan the table three times. However, cross apply is much more powerful than unpivot and requires less typing.
AFAIK, there is no different options other than usuing UNION operation. Basic purpose of UNION operation is that only ... combining records from multiple sources/result sets. So you can do like
select Id1 from tbl1
union
select Id3 from tbl1
union
select Id2 from tbl1
You could use UNPIVOT
SELECT Ids
FROM
(
SELECT Id1, Id2, Id3
FROM CTE
) d
UNPIVOT
(
Ids for id in (Id1, Id2, Id3)
) u
Use UNPIVOT table to get your result :
CREATE TABLE #table( Id1 INT ,Id2 INT , Id3 INT )
INSERT INTO #table( Id1 ,Id2 , Id3 )
SELECT 1 , 2 , 3 UNION ALL
SELECT 5 , 4 , 1 UNION ALL
SELECT 6 , 5 , 2
SELECT _Result [Result]
FROM
(
SELECT Id1 ,Id2 , Id3
FROM #table
)A
UNPIVOT
(
_Result FOR Id IN (Id1 , Id2 , Id3)
) UNPvt

SQL Pivot for multiple columns [duplicate]

This question already has answers here:
SQL Server Pivot Table with multiple column aggregates
(3 answers)
Closed 7 years ago.
I have the below table 'EmpTemp':
Name | Category | Value1 | Value 2
John | Cat1 | 11 | 33
John | Cat2 | 22 | 44
I would like to have the below output for the table:
Name | Cat1_Value1 | Cat2_Value1 | Cat1_Value2 | Cat2_Value2
John | 11 | 11 | 33 | 44
I guess this give a basic idea of what kind of transformation i'm expecting. I have tried the below query that gives me a partial solution:
SELECT
Name,
Cat1 AS 'Cat1_Value1',
Cat2 AS 'Cat2_Value1',
FROM EmpTemp AS T
PIVOT
(
MAX(Value1)
FOR Category IN (Cat1, Cat2)
) AS PVT
The above query gives me the following result:
Name | Cat1_Value1 | Cat2_Value1
John | 11 | 11
I am stuck how can I extend this pivot query. Any help is appreciated in advance.
Here is a way to do it using Pivot.
First you need to unpivot the data then do the pivot
;with cte as
(
select name,val,col_name from yourtable
cross apply (values
(value1,Category+'value1'),
(value2,Category+'value2')
) cs(val,col_name)
)
select * from cte
pivot(max(val) for col_name in([Cat1value1],
[Cat1value2],
[Cat2value1],
[Cat2value2]
)) p
Here is a simple way of doing it without using the pivot syntax:
select name,
max(case when category = 'Cat1' then value1 end) as cat1_value1,
max(case when category = 'Cat2' then value1 end) as cat2_value1,
max(case when category = 'Cat1' then value2 end) as cat1_value2,
max(case when category = 'Cat2' then value2 end) as cat2_value2
from EmpTemp
group by name

Find distinct rows based on combination of two columns

I am having trouble finding a good solution to a problem in SQL.
Say I have table like this:
ID | A | A
--------------------
4427 | 2 | 3
4427 | 3 | 2
4427 | 3 | 5
4427 | 5 | 3
4427 | 1 | 3
4427 | 2 | 5
4427 | 3 | 1
Now I want to find the rows with a unique combination of ID and A. By this I mean that I only want to see the rows where the combination of A(1) and A(2) exists only once. For example the first two rows in the table is "the same" since the combination of 2 and 3 is the same as 3 and 2.
The expected result to my quesion would be:
ID | A | A
--------------------
4427 | 2 | 3
4427 | 3 | 5
4427 | 1 | 3
4427 | 2 | 5
I am using SQL Server 2008.
If I understand correctly, this would be a simple "distinct" query if you ALWAYS had the ColA with a value less then ColB. Given this, you can use a case statement to handle this, combined with a distinct operator.
Try this.
Select Distinct
ID,
Case When ColA < ColB Then ColA Else ColB End,
Case When ColA < ColB Then ColB Else ColA End
From YourTableHere
One way to do this. FYI, the output A1/A2 may have differnet order than original value. If you don't care the order, you may try this.
WITH cte AS (
SELECT ID,A1 AS A, ROW_NUMBER() OVER (ORDER BY A1,A2) AS rn FROM Table1
UNION ALL
SELECT ID,A2 AS A, ROW_NUMBER() OVER (ORDER BY A1,A2) AS rn FROM Table1
)
SELECT DISTINCT ID, MIN(A) AS A1, MAX(A) AS A2
FROM cte
GROUP BY ID, rn
SQL Fiddle

transposing rows to columns in postgres

I have a query that as the following rows:
Id | key | Value
1 Type.name.1 Value1
2 Type.name.2 Value2
3 Type.desc.1 Desc1
4 Type.desc.2 Desc2
And I need a query that returns this:
Type.NameId | Type.DescId
1 3
2 4
How can I do this in Postgres?
SELECT *
FROM (
SELECT right(key, -10) AS name_id
WHERE "value" ~~ 'Value%'
) n
FULL JOIN (
SELECT right(key, -10) AS name_id, id AS desc_id
WHERE "value" ~~ 'Desc%'
) d USING name_id;
Exact form depends on a lot of details missing in your question.
Your table design and naming convention give me the shivers.