Select records where all rows have same value in two columns - sql

Here is my sample table
Col1 Col2
A 1
B 1
A 1
B 2
C 3
I want to be able to select distinct records where all rows have the same value in Col1 and Col2. So my answer should be
Col1 Col2
A 1
C 3
I tried
SELECT Col1, Col2 FROM Table GROUP BY Col1, Col2
This gives me
Col1 Col2
A 1
B 1
B 2
C 3
which is not the result I am looking for. Any tips would be appreciated.

Try this out:
SELECT col1, MAX(col2) aCol2 FROM t
GROUP BY col1
HAVING COUNT(DISTINCT col2) = 1
Output:
| COL1 | ACOL2 |
|------|-------|
| A | 1 |
| C | 3 |
Fiddle here.
Basically, this makes sure that amount the different values for col2 are unique for a given col1.

Try this:
SELECT * FROM MYTABLE
GROUP BY Col1, Col2
HAVING COUNT(*)>1
For example SQLFiddle here

you can try either of the below -
select col1, col2 from
(
select 'A' Col1 , 1 Col2
from dual
union all
select 'B' , 1
from dual
union all
select 'A' ,1
from dual
union all
select 'B' ,2
from dual
)
group by col1, col2
having count(*) >1;
OR
select col1, col2
from
(
select col1, col2, row_number() over (partition by col1, col2 order by col1, col2) cnt
from
(
select 'A' Col1 , 1 Col2
from dual
union all
select 'B' , 1
from dual
union all
select 'A' ,1
from dual
union all
select 'B' ,2
from dual
)
)
where cnt>1;

Related

Ordering within ARRAY_AGG after GROUP BY in BigQuery [duplicate]

This question already has an answer here:
How to create lines from ordered groupbyed points in BigQuery?
(1 answer)
Closed 10 months ago.
I have a BigQuery table:
create or replace table `project.table.mock` as (
select 1 as col0, 'a' as col1, 'x' as col2
union all
select 2 as col0, 'a' as col1, 'y' as col2
union all
select 4 as col0, 'b' as col1, 'z' as col2
union all
select 8 as col0, 'b' as col1, 'X' as col2
union all
select 7 as col0, 'b' as col1, 'Y' as col2
)
Visualization:
I would like to group by column col1, and array_agg the results from col2. I would like to have the elements appearing in each array to be sorted by col0.
I am now at:
select array_agg(col2) as col1arrays from `project.table.mock` group by col1;
which gives me:
The desired output in the second row would be [z, Y, X] (as the row where z appears in col2 has 4 in col0, the row where Y appears in col2 has 7 in col0 and the row where X appears in col2 has 8 in col0, and 4 < 7 < 8.
How can I achieve ordering within array_agg, as described above, in BigQuery?
You can add ORDER BY clause in ARRAY_AGG() function.
SELECT ARRAY_AGG(col2 ORDER BY col1 ASC) AS col1arrays
FROM `project.table.mock`
GROUP BY col1;
https://cloud.google.com/bigquery/docs/reference/standard-sql/aggregate_functions#array_agg
WITH mock as (
select 1 as col0, 'a' as col1, 'x' as col2
union all
select 2 as col0, 'a' as col1, 'y' as col2
union all
select 4 as col0, 'b' as col1, 'z' as col2
union all
select 8 as col0, 'b' as col1, 'X' as col2
union all
select 7 as col0, 'b' as col1, 'Y' as col2
)
select array_agg(col2 ORDER BY col0) as col1arrays from mock group by col1;
output:
+------------+
| col1arrays |
+------------+
| [x,y] |
| [z,Y,X] |
+------------+

How to check 1 to 1 relationship in Oracle(in one table)

Suppose I have a table with many columns, but only two of them are important to me. I want to check for the 1 to 1 relationship between col1 and col2(and if col1 exists more then one record of col2 it must be shown). Here is my sql query:
select tbl1.col1, count(tbl1.col1)
from admin.table_1 tbl1
left join ( select col2,col1 from admin.table_1) tbl2
on tbl1.col1 = tbl2.col1 and tbl1.col2 = tbl2.col2
group by tbl1.col1
having count(tbl1.col1) >1;
Is my calculation correct? Maybe it can be improved?
You need to check there is one col2 for each col1 and the reflexive relationship that there is one col1 for each col2. You can perform these checks using an analytic COUNT function:
Oracle Setup:
CREATE TABLE TABLE_1 ( col1, col2 ) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 2 FROM DUAL UNION ALL
SELECT 2, 3 FROM DUAL UNION ALL
SELECT 4, 4 FROM DUAL UNION ALL
SELECT 5, 4 FROM DUAL;
Query:
SELECT col1, col2
FROM (
SELECT col1,
col2,
COUNT( col1 ) OVER ( PARTITION BY col2 ) AS col1_per_col2,
COUNT( col2 ) OVER ( PARTITION BY col1 ) AS col2_per_col1
FROM table_1
)
WHERE col1_per_col2 > 1
OR col2_per_col1 > 1;
Output:
COL1 | COL2
---: | ---:
2 | 2
2 | 3
4 | 4
5 | 4
db<>fiddle here
You can directly use the group by as following:
SELECT
TBL1.COL1,
COUNT(1)
FROM
ADMIN.TABLE_1 TBL1
GROUP BY
TBL1.COL1
HAVING
COUNT(DISTINCT TBL1.COL2) > 1;
Cheers!!
You can use exists :
select tbl1.col1, count(tbl1.col1)
from admin.table_1 tbl1
where exists ( select 1
from admin.table_1 tbl2
where tbl2.col1 = tbl1.col2 )
group by tbl1.col1
having count(tbl1.col1)>1

concatenate and de-dupe multiple rows

I have some incoming rows in the below format.
| Col1 | Col2 | Col3 |
| 1 | A | 1 |
| 1 | A | 1,2 |
| 1 | A | 1,3 |
| 1 | A | 2,4 |
Desired outputsql is
| Col1 | Col2 | Col3 |
| 1 | A | 1,2,3,4 |
Basically, group all rows based on Col1 and Col2 and then concatenate and remove duplicates from Col3.
SELECT COL1, COL2, {?????}
FROM TABLEA
GROUP BY COL1, COL2;
I could not think much at this moment. Any pointers would be much appreciated. I am inclined to WX2 database, but any ANSI compliant snippet would be helpful.
For Postgres use this:
select col1, col2, string_agg(distinct col3, ',') as col3
from (
select col1, col2, x.col3
from tablea, unnest(string_to_array(col3, ',')) as x(col3)
) t
group by col1, col2;
This is largely ANSI compliant except for the string_to_array() and string_agg() function.
You could try with transpose or concatenation functions. The difficulty comes from the fact that col3 is varchar and a conversion is needed to get the distinct values.
With MySQL :
SELECT col1, col2, GROUP_CONCAT(DISTINCT col3) AS col3 FROM
(SELECT col1, col2, CONVERT(SUBSTR(col3, 1), UNSIGNED INTEGER) AS col3 FROM (
SELECT 1 AS col1, 'A' AS col2, '1' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,2' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,3' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '2,4' AS col3
) AS t
UNION ALL
SELECT col1, col2, CONVERT(SUBSTR(col3, 3), UNSIGNED INTEGER) AS col3 FROM (
SELECT 1 AS col1, 'A' AS col2, '1' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,2' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,3' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '2,4' AS col3
) AS t1
) AS t2
WHERE col3 <> 0
Result :
col1 | col2 | col3
1 | A | 1,2,3,4
For SQL Server: first concatenate all col3 values using STUFF method and INSERT INTO CTE table.Based on this CTE tables split all rows as individual into single column based on CTE table.Finally concate all DISTINCT strings with help of STUFF.
CREATE TABLE #table ( Col1 INT , Col2 VARCHAR(10) , Col3 VARCHAR(10))
INSERT INTO #table ( Col1 , Col2 , Col3 )
SELECT 1 , 'A' , '1' UNION ALL
SELECT 1 , 'A' , '1,2' UNION ALL
SELECT 1 , 'A' , '1,3' UNION ALL
SELECT 1 , 'A' , '2,4'
;WITH CTEValues ( Colval ) AS
(
SELECT STUFF ( ( SELECT ',' + Col3 FROM #table T2 WHERE T2.Col2 =
T1.col2 FOR XML PATH('') ),1,1,'')
FROM #table T1
GROUP BY Col2
)
SELECT * INTO #CTEValues
FROM CTEValues
;WITH CTEDistinct ( SplitValues , SplitRemain ) AS
(
SELECT SUBSTRING(Colval,0,CHARINDEX(',',Colval)),
SUBSTRING(Colval,CHARINDEX(',',Colval)+1,LEN(Colval))
FROM #CTEValues
UNION ALL
SELECT CASE WHEN CHARINDEX(',',SplitRemain) = 0 THEN SplitRemain ELSE
SUBSTRING(SplitRemain,0,CHARINDEX(',',SplitRemain)) END,
CASE WHEN CHARINDEX(',',SplitRemain) = 0 THEN '' ELSE
SUBSTRING(SplitRemain,CHARINDEX(',',SplitRemain)+1,LEN(SplitRemain))
END
FROM CTEDistinct
WHERE SplitRemain <> ''
)
SELECT STUFF ( ( SELECT DISTINCT ',' + SplitValues FROM CTEDistinct T2
FOR XML PATH('') ),1,1,'')

Select distinct values based on multiple column from table

I am having below dummy table
select * from (
select 'A' as col1, 'B' as col2 from dual
union
select 'B' as col1, 'A' as col2 from dual
union
select 'A' as col1, 'C' as col2 from dual
union
select 'C' as col1, 'A' as col2 from dual
union
select 'A' as col1, 'D' as col2 from dual
)a
which will give output as below
col1 col2
A B
A C
A D
B A
C A
I wants to find the distinct values from that table like below
col1 col2
A B
A C
A D
first row can be A B or B A same as second can be A C or C A
Is it possible??
We got the solution for above problem which is below
select distinct least(col1, col2), greatest(col1, col2)
from the_table;
but if there is more than 2 column, then i wouldn't work
Let us assume the below scenario
Input
col1 col2 col3
A B E
A C E
A D E
B A F
C A E
Output
col1 col2 col3
A B E
A D E
B A F
C A E
then what would be the possible solution ?
Here is one method:
select col1, col2
from t
where col1 <= col2
union all
select col1, col2
from t
where col1 > col2 and
not exists (select 1 from t t2 where t2.col1 = t.col2 and t2.col2 = t.col1);
The following will work for Oracle and Postgres:
select distinct least(col1, col2), greatest(col1, col2)
from the_table;
Online example: http://rextester.com/BZXC69735
select DISTINCT * from (
select 'A' as col1, 'B' as col2 from dual
union
select 'B' as col1, 'A' as col2 from dual
union
select 'A' as col1, 'C' as col2 from dual
union
select 'C' as col1, 'A' as col2 from dual
union
select 'A' as col1, 'D' as col2 from dual
)a
select col1, col2 from t where col1 <= col2
union
select col2, col1 from t where col1 > col2

how to get the maximum occurrence value from a table for a combination?

I have the following table;
column 1 column 2 column 3
1 2 X
1 2 X
1 2 Y
1 3 Z
1 3 X
I need to write an SQL query to get the output as;
1 2 X (because X is the maximum occurrence)
1 3 Z or X(because number of occurrence of Z or X is same)
How do i do this ?
I think i have a solution for you, try this script using the functions RANK(), ROW_NUMBER() & DENSE_RANK(), you choose the function that fits with your needs :
with temp as (
select 1 as col1, 2 AS col2, 'X' as col3 union all
select 1 as col1, 2 AS col2, 'Y' as col3 union all
select 1 as col1, 2 AS col2, 'X' as col3 union all
select 1 as col1, 3 AS col2, 'Z' as col3 union all
select 1 as col1, 3 AS col2, 'T' as col3 union all
select 1 as col1, 3 AS col2, 'Y' as col3 union all
select 1 as col1, 3 AS col2, 'Y' as col3 union all
select 1 as col1, 4 AS col2, 'Y' as col3 union all
select 1 as col1, 4 AS col2, 'W' as col3)
,temp2 AS (
select
col1
,col2
,col3
,COUNT(1) nb_occurence
,RANK() OVER(PARTITION BY col1,col2 ORDER BY COUNT(1) DESC) Ordre_RANK
,ROW_NUMBER() OVER(PARTITION BY col1,col2 ORDER BY COUNT(1) DESC) Ordre_ROW_NUMBER
,DENSE_RANK() OVER(PARTITION BY col1,col2 ORDER BY COUNT(1) DESC) Ordre_DENSE_RANK
from temp
GROUP BY
col1
,col2
,col3 )
SELECT *
FROM temp2
--WHERE Ordre_RANK = 1
--WHERE Ordre_ROW_NUMBER = 1
--WHERE Ordre_DENSE_RANK = 1
I hope this will help you.