Distinct by comparing multiple columns SQL - sql

I have a select query
Select col1,col2,col3
from table;
The table contains following rows
col1 col2 col3
A | B | C
B | A | C
C | B | C
I need to get the distinct result which contains a single combination A,B,C by comparing multiple columns.
Result Should be some thing like
col1 col2 col3
A | B | C
the order can be changed of result rows.
How can I achieve this ?

Please try out this, I am not sure about you proper requirement. But on sample data given above. I have came across this solution,
With CTE as
(
Select MIN(col1) as col1 from MyTable
)
Select * from CTE
cross apply
(
Select MIN(col2) as col2 from MyTable
where col2 <> CTE.col1
)as a
cross apply
(
Select MIN(col3) as col3 from MyTable
where col3 not in (CTE.col1,a.col2)
)as b
DEMO HERE

SELECT *
FROM table
WHERE (col1 = 'A' AND col2 = 'B' AND col3 = 'C')

You can also go with this below query if the number of column and the values are known.
The CASE statement is the closest to IF in SQL
SELECT
CASE
WHEN (col1 = 'A' and col2 = 'B' and col3='C') or (col1 = 'C' and col2 = 'A' and col3='B') or (col1 = 'B' and col2 = 'C' and col3='A' )
THEN 1
ELSE 0
END as RESULT, *
FROM table
From the result you can take the required output by checking the value of RESULT==1(integer)
If you want the result as a boolean value then do the CAST like ,
SELECT
CAST(
CASE
WHEN (col1 = 'A' and col2 = 'B' and col3='C') or (col1 = 'C' and col2 = 'A' and col3='B') or (col1 = 'B' and col2 = 'C' and col3='A' )
THEN 1
ELSE 0
END as RESULT_INT)
as RESUTL, *
FROM table

Related

How to calculate how many null values are present in each column?

I have a table A like this :
col1col2col3
1 0null
nullnullnull
3nullnull
null 5 1
I want an output like this in Oracle 10G :
column_namenull_count
col1 2
col2 2
col3 3
I have achieved this using UNION ALL like this:
select "col1" column_name,sum(case when col1 is null then 1 else 0 end) as null_count from A group by "col1"
union all
select "col2" column_name,sum(case when col2 is null then 1 else 0 end) as null_count from A group by "col2"
union all
select "col3" column_name,sum(case when col3 is null then 1 else 0 end) as null_count from A group by "col3";
It is working fine , but it is taking lots of time , as there are nearly 100 UNION ALLs . I want to achieve the same output without using UNION ALL.
Is there any way to achieve this without using UNION ALL ?
You can use UNPIVOT for that (I am not sure if the ancient Oracle 10 already supported that - I haven't used that for over a decade)
select colname, count(*) - count(val) as num_nulls
from t1
UNPIVOT include nulls
(val for colname in (col1 as 'C1',
col2 as 'C2',
col3 as 'C3'))
group by colname
order by colname;
Not sure if that is faster though.
Online example: https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=4e807b8b2d8080abac36574f776dbf04
Oracle 10g doesn't support the UNPIVOT and PIVOT operators, so to do what you're after in 10g, you'd need to use a dummy table (containing the same number of rows as columns being unpivoted - in your case, that's 3), like so:
WITH your_table AS (SELECT 1 col1, 0 col2, NULL col3 FROM dual UNION ALL
SELECT NULL col1, NULL col2, NULL col3 FROM dual UNION ALL
SELECT 3 col1, NULL col2, NULL col3 FROM dual UNION ALL
SELECT NULL col1, 5 col2, 1 col3 FROM dual)
SELECT CASE WHEN dummy.id = 1 THEN 'col1'
WHEN dummy.id = 2 THEN 'col2'
WHEN dummy.id = 3 THEN 'col3'
END column_name,
COUNT(CASE WHEN dummy.id = 1 THEN CASE WHEN col1 IS NULL THEN 1 END
WHEN dummy.id = 2 THEN CASE WHEN col2 IS NULL THEN 1 END
WHEN dummy.id = 3 THEN CASE WHEN col3 IS NULL THEN 1 END
END) null_count
FROM your_table
CROSS JOIN (SELECT LEVEL ID
FROM dual
CONNECT BY LEVEL <= 3) dummy
GROUP BY dummy.id;
COLUMN_NAME NULL_COUNT
----------- ----------
col1 2
col2 2
col3 3
If you think that will take an age to write for a large number of columns, you can always write a query that will generate the bulk of the case statements yourself, e.g.:
SELECT 'when dummy.id = '||row_number() OVER (PARTITION BY owner, table_name ORDER BY column_id)||' then '''||LOWER(column_name)||'''' first_part,
'when dummy.id = '||row_number() OVER (PARTITION BY owner, table_name ORDER BY column_id)||' then case when '||column_name||' is null then 1 end' second_part
FROM all_tab_columns a
WHERE owner = ...
AND table_name = ...
-- and column_name in (...)
ORDER BY column_id;
(I included the row_number() analytic function rather than using column_id because if you're excluding some columns, the column_id column will no longer be consecutive numbers starting with 1.)

Print value in SQL depending on its presence in another column

I have a table of the form
Col1 | Col2
-------------
A | C
B | A
C | X
D | A
E | NULL
If any element of Col1 is present in Col2, then It should be printed as
Element, YES.
If it is not present in Col2, then it needs to be printed as element, NO and if corresponding col2 value is NULL then it needs to be printed as element, NULL
So final output should look like
A YES
B NO
C YES
D NO
E NULL
I was able to write three individual queries for the same but am struggling with the moment on how to put them inside Case statements in SQL.
SELECT Col1 FROM table WHERE col1 IN (SELECT col2 FROM table)
Select col1 FROM table where Col2 is NULL
SELECT Col1 FROM table WHERE col1 NOT IN (SELECT col2 FROM table)
I tried putting them inside case statements
Select col1, Case
when (SELECT Col1 FROM table WHERE col1 IN (SELECT col2 FROM table))
then "YES"
when (Select col1 FROM table where Col2 is NULL)
then "NULL"
else
"NO"
But I was getting an error. How should I fix this?
I would expect the query to look like this:
select col1,
(case when col2 is null then NULL
when col1 in (select t2.col2 from t t2)
then 'YES'
else 'NO'
end)
from t;

Select from table group by id where all records in that group have a flag = false

My Table:
ID|Col1|Col2|
1 |abc |1 |
2 |abc |0 |
3 |xyz |0 |
4 |xyz |0 |
5 |jkl |1 |
Q1. I want to return a list of records grouped by Col1 where all of the records in that group have Col2 = 0. I don't mind if it returns all of them (record 3 and 4) or just unique one(e.g. just 'xyz').
Q2. I also would like to get a list of records grouped by Col1 where any of the records in that group have Col2 = 1 (in this case 'abc' and 'jkl')
select col1
from your_table
group by col1
having sum(case when col2 = 1 then 1 else 0 end) = 0
and
select col1
from your_table
group by col1
having sum(case when col2 = 1 then 1 else 0 end) > 0
And another ways, using EXISTS and sub-queries:
select *
from your_table
where not exists (select * from your_table t2 where col1 = t2.col1 and col2 <> 0)
And
select *
from your_table
where exists (select * from your_table t2 where col1 = t2.col1 and col2 = 1)
This might helps you
declare #t table(a char(1), b int)
insert into #t values ('a',0),('b',1),('a',0),('b',0)
for first
select distinct * from #t
where a not in (select a from #t where b=1)
for second
select distinct * from #t
where a in (select a from #t where b=1)
vote this if it helps you
Try Conditional Aggregation:
DECLARE #table TABLE(ID INT, Col1 VARCHAR(30), Col2 INT)
INSERT INTO #table VALUES
(1,'abc',1),
(2,'abc',0),
(3,'xyz',0),
(4,'xyz',0),
(5,'jkl',1)
SELECT Col1
FROM #table
GROUP BY Col1
HAVING SUM(CASE
WHEN Col2 = 0 THEN 1
ELSE 0
END) = COUNT(*)
SELECT Col1
FROM #table
GROUP BY Col1
HAVING SUM(CASE
WHEN Col2 = 1 THEN 1
ELSE 0
END) > 0
You have already marked another answer, but you can even tune it, because in this particular case you don't need cases in having clause. Actually you will need cases when col2 is not numeric type, say varchar
Select col1 from table
group by col1
having sum(col2)=0
Select col1 from table
group by col1
having sum(col2)>0

SQL UPDATE Select row based on column cross referenced values

I would like to do an update to a row based on a value in another column.
Example table
Col1 Col2 Col3
'A' | '' | 100
'B' | '' | 120
'C' | 'A' | 0
UPDATE Table SET Col3 = Col3 - 10 WHERE Col1 = 'A'
However, if Col2 is not blank then I want to update the row that has it's value in Col2 so that
UPDATE Table SET Col3 = Col3 - 10 WHERE Col1 = 'C'
would update the Col1 = 'A' row
update
I discovered the following query works for me
UPDATE Table SET col3 = Col3 - 10
WHERE Col2 = '' and Col1 = 'C'
OR Col1 = (SELECT Col2 FROM Table WHERE Col1 = 'C')
where tbl is the table name
update tbl set col3=col3-10
from tbl t
inner join tbl tt
on t.col1=tt.col2 or t.col2=''
where t.col1 = 'C'

SQL assigning a value after testing against multiple columns

I have two columns:
INPUT
col1 col2
1 0
1 0
1 0
2 1
2 0
3 0
3 0
3 1
3 1
Let's suppose col1 holds some entity ID number, which is repeated. I'm testing whether this entity ID contains value 1 in col2. So if entity ID has 1 in corresponding col2 then I create another col3 with "NO"/"YES" values or just "0"/"1" accrodingly.
OUTPUT
col1 col3
1 NO
2 YES
3 YES
SELECT Col1, MAX(CASE WHEN col2 = 1 THEN 1 ELSE 0 END) Col3
FROM YourTable
GROUP BY Col1
UPDATED
Well, since the query above doesn't work for you, you can try the following:
SELECT Col1, MAX(Col3) Col3
FROM ( SELECT Col1,
CASE WHEN col2 = 1 THEN 1 ELSE 0 END AS Col3
FROM YourTable) A
GROUP BY Col1
UPDATE table
SET
col3 = DECODE(col2, 1, 'YES', 'NO');
If you want to run this for a given entity id only:
UPDATE table
SET
col3 = DECODE(col2, 1, 'YES', 'NO')
WHERE
col1 = yourid;
If your column 3 does not exist, you'll have to create it before hand anyway:
ALTER TABLE table ADD (col3 NUMBER NOT NULL);
SELECT Col1,
CASE WHEN MAX(Col2) = 1 THEN 'YES' ELSE 'NO' END AS Col3
FROM TableName
GROUP BY Col1
SQLFiddle Demo
SELECT DISTINCT col1,
CASE WHEN EXISTS(SELECT * FROM MyTab WHERE col1 = M.col1 AND col2 = 1)
THEN 'Yes' ELSE 'No' AS col3 FROM MyTab M