Ambiguous column name when putting together several nested SELECT statements - google-bigquery

Trying to use a snippet of code from https://gist.github.com/fhoffa/411cd5ac0d7b8bd2b17a.
Getting this error message:
Column name c1 is ambiguous at [1:24]
SELECT 'c1' AS column, c1 AS value, rowid
FROM
(SELECT 1 c1, 2 c2, 3 c3, 'id1' rowid),
(SELECT 9 c1, 2 c2, 3 c3, 'id2' rowid),
(SELECT 4 c1, 1 c2, 3 c3, 'id3' rowid)
This code was posted 8 years ago.
It may have worked at that time but it is not working now.
I appreciate any feedback.
Thanks

Using 'UNION ALL' got rid of the error.
Also, there must be an extra parenthesis needed to
group these 3 select statements.
Without the parenthesis, a misleading error message shows up:
Something like first select has 3 columns but the second select has
4 columns. Weird error message.
SELECT 'c1' AS column, c1 as value, rowid
FROM
(
(SELECT 1 c1, 2 c2, 3 c3, 'id1' as rowid)
UNION ALL
(SELECT 9 c1, 2 c2, 3 c3, 'id2' as rowid)
UNION ALL
(SELECT 4 c1, 1 c2, 3 c3, 'id3' as rowid)
)

Related

How to do aggregation with calculation in SQL

I have similar table with two columns, C2 will have multiple values . I need the output as
Condition for t2.c2 is If all the values in t1.C2 are <= 5, then 1 else 0, please advice what would be the best logic.
Another option
select distinct C1,
if(logical_and(C2 <= 5) over(partition by C1), 1, 0) as C2
from your_table
if applied to sample data in your question - output is
This will give desired result. First section has t1 table data, second section has t2 data based on logic requested.
with t1 as
(select 'A10' as C1, 2 as C2 union all
select 'A10' as C1, 3 as C2 union all
select 'A10' as C1, 4 as C2 union all
select 'A10' as C1, 5 as C2 union all
select 'A10' as C1, 3 as C2 union all
select 'A10' as C1, 4 as C2 union all
select 'A10' as C1, 2 as C2 union all
select 'A10' as C1, 4 as C2 union all
select 'A10' as C1, 5 as C2 union all
select 'A10' as C1, 3 as C2 )
select C1 , if(MAX(C2) <=5,1,0) as C2
from t1 group by C1;

oracle transposing rows to columns

my question is about transposing rows into columns.
I have got table T1(c1,c2,c3,c4,c5) columns with datatype varchar2, i want to transpose the rows obtained,
example:
select * from T1
gives
c1 c2 c3 c4 c5
row1 1 2 3 4 5
row2 A B C D E
....
rown U V W X Y
the result expected is
C1 1 A......U
C2 2 B......V
C3 3 C......W
C4 4 D......X
C5 5 E......Y
all rows in different columns(table contains only 10-15 rows)
i have tried the following query, but it isnt giving expected result.
Select RN,value
From (
Select x.*,row_number ()
Over ( Order By c1) rn From T1 x)
Unpivot (value For value_type In (C1,c2,c3,c4,c5)
);
So you only need to pivot data again:
dbfiddle demo
select *
from (
select rn, val, col
from (select t1.*, row_number() over (order by c1) rn from t1)
unpivot (val for col in (c1, c2, c3, c4, c5)))
pivot (max(val) for rn in (1, 2, 3, 4))
order by col
You have to know how many rows are in t1 and list them all in pivot in clause (1, 2, 3, 4) alternatively adding aliases for each column.

SQL combine basic order by and custom order by

I am using Oracle database and I am trying to combine a basic Order By and a custom one in one of my query.
Here's my table :
table1
-----------------
C1 | C2 | C3 | C4
I am trying to order it like that :
SELECT C1,C2,C3,C4 FROM table1
ORDER BY C1, C2, C3, (
CASE C4
WHEN C4 = 'value1' THEN 1
WHEN C4 = 'value2' THEN 2
WHEN C4 = 'value3' THEN 3
END
)
But I'm getting "Missing keyword" and I can't find which one, any ideas?
You can try
SELECT C1,C2,C3,C4 FROM table1
ORDER BY C1, C2, C3, (
CASE
WHEN C4 = 'value1' THEN 1
WHEN C4 = 'value2' THEN 2
WHEN C4 = 'value3' THEN 3
END
)
OR
SELECT C1,C2,C3,C4 FROM table1
ORDER BY C1, C2, C3, (
CASE C4
WHEN 'value1' THEN 1
WHEN 'value2' THEN 2
WHEN 'value3' THEN 3
END
)

count of distinct columns in a record

How to count distinct columns values for a record
C1 C2 C3 C4
1 USER1 USER2 USER3
2 USER1 USER1 USER2
3 USER2 USER3 USER3
4 USER1 USER1 USER1
OUTPUT:
C1 COUNT
1 3
2 2
3 2
4 1
How to calculate distinct number of users in each record. Is there a way other than comparing column values.
Thanks.
One way is with unpivot:
select c1, count(distinct col) as cnt from (
select * from your_table
unpivot( col for lst in(C2, C3, C4) )
) tt
group by c1
For only three comparison columns this is the simplest thing which would work:
with cte as (
select c1, c2 from your_table
union
select c1, c3 from your_table
union
select c1, c4 from your_table
)
select c1, count(c2) as cnt
from cte
group by c1
/
The union operator produces a distinct set which feeds into the aggregated count.
with cte as (
select c1, c2 from your_table
union all
select c1, c3 from your_table
union all
select c1, c4 from your_table
)
select c1, count(c2) as cnt,count(distinct c2) as distinct_cnt
from cte
group by c1
/

SQL - find rows that have the same set of values in a column

I have a table and I want to select all rows that have exactly the same set of values that appear in a column and return them as a pair of a certain column.
For example, let's say I have a table named Table:
C1 C2
1 1
1 2
1 3
2 1
3 1
3 2
3 3
4 1
4 2
When I run my query, it should return the row:
1 3
because these are the two values in C1 that have the same set of values in column C2 (1,2,3).
I have an incorrect query below that returns all rows that have at least one matching value in C2 and I can't figure out how to correct it.
SELECT DISTINCT T1.C1, T2.C1
FROM Table T1, Table T2
WHERE T1.C1 != T2.C1
AND T1.C2 = T2.C2
AND T1.C1 < T2.C1
GROUP BY s1.suppId, s2.suppId;
Any help would be greatly appreciated, thanks.
As you do not specify, this one will handle the case of two sets of matching C2 values, outputting two rows - one for each matched set.
with thetable as (
SELECT 1 C1, 1 c2 from dual union
SELECT 1 C1, 2 c2 from dual union
SELECT 1 C1, 3 c2 from dual union
SELECT 2 C1, 1 c2 from dual union
SELECT 3 C1, 1 c2 from dual union
SELECT 3 C1, 2 c2 from dual union
SELECT 3 C1, 3 c2 from dual union
SELECT 4 C1, 1 c2 from dual union
SELECT 4 C1, 2 c2 from dual union
-- added fourrows to give a second set of matches
SELECT 5 C1, 1 c2 from dual union
SELECT 5 C1, 2 c2 from dual union
SELECT 6 C1, 1 c2 from dual union
SELECT 6 C1, 2 c2 from dual )
SELECT LIST_C2, List_c1
FROM (
SELECT list_c2
,LISTAGG(c1,',') WITHIN GROUP (ORDER BY c1) list_c1
FROM (
SELECT c1, LISTAGG(c2,',') WITHIN GROUP (ORDER BY c2) list_c2
FROM thetable
GROUP BY c1
)
group by list_c2
)
-- only bring back where we had more than one c1
WHERE instr(list_c1,',') != 0
Showing the following two sets of C2 values and their matching lists of C1s
LIST_C2 LIST_C1
"1,2" "4,5,6"
"1,2,3" "1,3"
listagg is the rescue (instead of count as commented by #Juan)
with lst as (
select c1, LISTAGG(c2, '; ') WITHIN GROUP (ORDER BY c2) c2_lst
from tst
group by c1
)
select lst1.c1 c1a, lst2.c1 c1b
from lst lst1
inner join lst lst2
on lst1.c2_lst = lst2.c2_lst and
lst1.c1 < lst2.c1
;
gives as requested
1 3
SQLFiddleDemo
Also be prepared, this works only small data (the concatenated key is limited with 4000 bytes).
UPDATE
listagg concatenates all values in the group. To get only distinct values (i.e. set of values) an additional query with DISTINCT must be performed.
WITH lst AS
( SELECT DISTINCT c1,c2 FROM tst
),
lst_dist AS
(SELECT c1,
LISTAGG(c2, '; ') WITHIN GROUP (
ORDER BY c2) c2_lst
FROM lst
GROUP BY c1
)
SELECT lst1.c1 c1a,
lst2.c1 c1b
FROM lst_dist lst1
INNER JOIN lst_dist lst2
ON lst1.c2_lst = lst2.c2_lst
AND lst1.c1 < lst2.c1
You can do this without list agg, using a self join:
select t1.c1, t2.c1
from (select t.*, count(*) over (partition by c1) as cnt
from table t
) t1 join
(select t.*, count(*) over (partition by c1) as cnt
from table t
) t2
on t1.c2 = t2.c2 and t1.c1 < t1.c2 and t1.cnt = t2.cnt
group by t1.c1, t2.c1
having count(*) = max(t1.cnt);
Note: this assumes that there are no duplicate rows in the table. A slight variation can work in that case as well.
This joins the rows on the second column and then aggregates by the first. Along the way, it makes sure that the number of matching columns is the same in the two table and that all columns match.