Oracle function to distinct NULL values based on other column - sql

I am looking for the simplest solution that will resolve following problem.
I have a table:
Column1 Column2
------- -------
A 11
A NULL
B 12
B 14
B NULL
C NULL
I would like to query(Select) this table to achive only NULL value when this is the only value for distinct value of column1. When there is at least one non null value with column1 it is important to bypass then null values for them. Desired outcome:
Column1 Column2
------- -------
A 11
B 12
B 14
C NULL
I was trying with COALESCE, NULLIF.. etc and had no results. I would like to achieve this with simplest solution. I am joining then Column2 with column in other table but for NULL I hope left join could be appropriate .
I am very grateful for any help

Try this:
SELECT column1, column2
FROM dummy t1
WHERE column2 IS NOT NULL
OR NOT EXISTS (SELECT ''
FROM dummy t2
WHERE t1.column1 = t2.column1
AND column2 IS NOT NULL)
Keeps all rows for which column2 either not NULL or are NULL and are the only within in a group.

Should work like this ( there might be a more perfomant way though )
select column1, column2
from table where column2 is not null
union
( select column1, column2
from table
where column2 is null
and column1 not in ( select column1
from table
where column2 is not null
group by column1)
)
The first select above the union gets all rows without null values, then the second one simply adds all rows with null values in column2, but not the ones you had allready an the first one. group by not necessary for the result, but might clearify the logic.

You can use a left join, first get the values you need from the table and then join it to itself.
Shown here as a CTE for clarity.
WITH Col1Values AS
(
SELECT DISTINCT Column1
FROM Table
)
SELECT Col1Values.Column1, T2.Column2
FROM Col1Values
LEFT JOIN Table T2 ON Col1Values.Column1 = T2.Column1
or with a sub-query
SELECT T1.Column1, T2.Column2
FROM (
SELECT DISTINCT Column1
FROM Table
) T1
LEFT JOIN Table T2 ON T1.Column1 = T2.Column1

Inner query: Use analytic function to compute how many non-null C2 values each C1 has
Outer query: filter for rows with non-null C2 or count-distinct-C2=0
SELECT C1, C2
FROM (
SELECT C1, C2, COUNT(C2) OVER (PARTITION BY C1) C2_COUNT
FROM TABLE
)
WHERE C2 IS NOT NULL OR C2_COUNT = 0;
Join version of same solution (no analytic functions)
SELECT C1, C2
FROM TABLE
NATURAL INNER JOIN
(SELECT C1, COUNT(C2) C2_COUNT
FROM TABLE GROUP BY C1)
WHERE C2 IS NOT NULL OR C2_COUNT = 0;

Try this
select c1, c2 from t where c2 in (select distinct c2 from t where c2 is not null);

Related

SQL Union two tables and keep table name in a column

I am trying to UNION two tables whilst retaining information about which table the entry is from.
For example, given this input
Table A
Column1 Column2
0 X
1 Y
Table B
Column1 Column2
3 Z
1 Y
I want to end up with this:
Table C
Column1 Column2 Column3
0 X A
1 Y A
3 Z B
I tried an INSERT INTO statement but I can't insert different text in Column3 without getting all the duplicates from e.g. Table 2
You want full outer join :
SELECT COALESCE(a.col1, b.col1), COALESCE(a.col2, b.col2),
(CASE WHEN a.col1 IS NOT NULL
THEN 'A'
ELSE 'B'
END)
FROM tableA a FULL OUTER JOIN
tableB b
ON b.col1 = a.col1;
you can use window function row_number()
with cte as
(
select column1,column2,'A' as column3 from tableA
union all
select column1,column2,'B' as column3 from tableB
) , cte2 as
(
select * , row_number() over(partition by column1,column2 order by column3 ) rn
from cte
) select column1,column2,column3 from cte2 where rn=1
demo link
You can try to use UNION combine tableA and tableB then use outer join with CASE WHEN to make it.
WITH CTE AS (
SELECT Column1,Column2
FROM TableA
UNION
SELECT Column1,Column2
FROM TableB
)
SELECT t1.*,(case when t2.COLUMN1 is NOT null THEN 'A' ELSE 'B' END) Column3
FROM CTE t1
LEFT JOIN TableA t2 on t1.COLUMN1 = t2.COLUMN1 and t1.COLUMN2 = t2.COLUMN2
sqlfiddle
Column1 Column2 Column3
0 X A
1 Y A
3 Z B
You seem to want rows from a and then other rows from b. This is not exactly a union.
I would approach this as:
select a.column1, a.column2, 'a' as column3
from a
union all
select b.column1, b.column2, 'b' as column3
from b
where not exists (select 1 from a where a.column1 = b.column1);
Something like this could be the solution you seek.
SELECT Column1, Column2, 'A' AS Column3
FROM [Table A]
UNION
SELECT Column1, Column2, 'B' AS Column3
FROM (
SELECT Column1, Column2
FROM [Table B]
EXCEPT
SELECT Column1, Column2
FROM [Table A]
) b
It's strange to me that it doesn't work. Your requirements can be translated as:
Take all rows from set A and add column with value A.
Take all rows from set B which are not in set A and and add
column with value B.
Return both results from step 1 and 2.
And this is what this query is doing.

SQL to get the common rows from two tables

I have two tables T1 and T2.
Can any one please help with a SQL query which will fetch the common rows from these two tables? (Assume T1 and T2 has 100 columns each)
P.S : I guess INNER JOIN on each of the columns will not be a good idea.
Thanks
If you are using SQL Server 2005, then you can use Intersect Key word, which gives you common records.
SELECT column1
FROM table1
INTERSECT
SELECT column1
FROM table2
If you want in the output both column1 and column2 from table1 which has common columns1 in both tables.
SELECT column1, column2
FROM table1
WHERE column1 IN
(
SELECT column1
FROM table1
INTERSECT
SELECT column1
FROM table2
)
Use INTERSECT
SELECT * FROM T1
INTERSECT
SELECT * FROM T2
Yes, INNER JOIN will work.
eg. SELECT (column_1, column_2, ... column_n) FROM T1 JOIN T2 ON (condition) WHERE (condition)
This query will fetch the common records (intersection of) in both the tables according to ON condition.
select
t1.*
from
t1, t2
where
(
(t1.col1 is null and t2.col1 is null) or (
(t1.col1 = t2.col1 )
) and
(
(t1.col2 is null and t2.col2 is null) or (
(t1.col2 = t2.col2 )
) and
(
(t1.col3 is null and t2.col3 is null) or (
(t1.col3 = t2.col3 )
) and
....
(
(t1.col100 is null and t2.col100 is null) or (
(t1.col100 = t2.col100 )
)
SELECT NAME FROM Sample1
UNION
SELECT NAME FROM Sample2;
EX: Table Sample1
ID NAME
-------
1 A
-------
2 B
-------
Table Sample 2
ID NAME
--------
1 C
--------
2 B
------
Output
NAME
----
A
---
B
---
C
---

SQL - Null value should match with not null value with another table

Table 1
Column1 Column2 Column 3
A Null 12
B Null 15
C 0 15
Table 2
Column2 Column3
0 15
0 12
I have table 1 and Table 2 , Here I'm passing table 2 parameters to table 1 which should return the column1 but it should match with Null values like the below scenario
If I pass (0, 15) to table 1 then it should return 'C' not 'B'.
If I Pass (0,12) to table 1 then it should return 'A'
Anytime it should return one value not multiple vales.
Could you please help me with this logic ?
You could do this as a union:
select Column1 from
(
select Table1.Column1 as Column1,Table1.Column2 as Column2
from Table1
join Table2 on
Table1.Column2=Table2.Column2 and Table1.Column3=Table2.Column3
UNION
select Table1.Column1 as Column1,Table1.Column2 as Column2
from Table1
join Table2 on
Table1.Column2 is NULL and Table1.Column3=Table2.Column3
) as Unioned
ORDER BY Column2 NULLS LAST
LIMIT 1;
The UNION discards duplicates, but you could always wrap the entire statement in another SELECT if you explicitly need to tell it to return at most one value.
select *
from table2 t
left outer join table1 t1 on t.column2=t1.column2 and t.column3=t1.column3
left outer join table1 t2 on t2.column2 is null and t.column3=t2.column3
where t1.column2 is not null or t2.column3 is not null
SQL Server
WITH T1
as
(SELECT COLUMN1,COLUMN2,
case when COLUMN2 is null then 0 else COLUMN2 end AS TRANSFORMED_COLUMN2,
row_number() OVER (partition by isnull(column3,2) ORDER BY isnull(COLUMN2,2) asc) AS rnk,
COLUMN3
FROM TABLE1)
SELECT
T1.COLUMN1,
T2.COLUMN2,
T2.COLUMN3
FROM
T1
INNER JOIN
(SELECT COLUMN2,COLUMN3 FROM TABLE2) T2
ON T1.TRANSFORMED_COLUMN2 = T2.COLUMN2
AND T1.COLUMN3=T2.COLUMN3
where T1.rnk=1
By using CTE, you will running through the tables just once.
SELECT t1.* FROM table1 t1
INNER JOIN table2 t2
ON NVL(t1.column2,0) = t2.column2 and t1.column3 = t2.column3

SQL Table with a list of repeating values (duplicates) to find

I am trying to identify a list of duplicates from a table and my table looks like this:
Column1-Column2
1-1
1-2
1-3
2-1
2-2
2-3
3-1
3-2
3-4
4-1
4-2
4-3
4-4
5-1
5-2
5-4
1 has a group of {1,2,3}
2 has a group of {1,2,3}
And are duplicates
3 has a group of {1,2,4}
5 has a group of {1,2,4}
And are duplicates
4 has a group of {1,2,3,4}
And has no friends ;)
Column 2 really is a varchar column, but I made everything numbers for simplicity sack.
I have been playing with CheckSum_Agg, but it has false positives. :(
My output would look something like this:
1,2
3,5
Where I select the min ID for the first column and all of the other values for the second column. Non-duplicates are omitted.
Another example might look like:
1,2
1,6
3,5
3,7
3,8
(Notice no "4" in the list, I just added other "pairs" for show that 1 and 3 are the lowest. If 4 is in the list like 4,0 or 4,null, I can make that work too.)
I'm using SQL Server 2012. Thanks!
WITH t AS (
SELECT
column1,
COUNT(*) c
FROM MyTable
GROUP BY column1
)
SELECT
t1.column1,
t2.column1
FROM t t1
INNER JOIN t t2 ON (
t1.c = t2.c AND
t2.column1 > t1.column1
)
WHERE NOT EXISTS (
SELECT column2 FROM MyTable WHERE column1 = t1.column1
EXCEPT
SELECT column2 FROM MyTable WHERE column1 = t2.column1
)
select column1,column2 from my_table
group by column1,column2
having COUNT(*) > 1
will give you list of duplicate records.
--This code produced the results I was looking for in the original post.
WITH t AS (
SELECT
column1,
COUNT(*) c
FROM #tbl
GROUP BY column1
),
tt AS(
SELECT
t1.column1 as 'winner',
t2.column1 as 'loser'
FROM t t1
INNER JOIN t t2 ON (
t1.c = t2.c AND
t1.column1 < t2.column1
)
WHERE NOT EXISTS (
SELECT column2 FROM #tbl WHERE column1 = t1.column1
EXCEPT
SELECT column2 FROM #tbl WHERE column1 = t2.column1
)
)
SELECT fullList.winner, fullList.loser
FROM
( SELECT winner FROM tt tt1
EXCEPT
SELECT loser FROM tt tt2
) winnerList
JOIN tt fullList on winnerList.winner = fullList.winner
ORDER BY fullList.winner, fullList.loser

Select rows where column A and column B do not exist as a row in another table

I have this
SELECT COLUMN1, COLUMN2, COLUMN3
FROM TABLE_A
WHERE NOT COLUMN1 IN (SELECT COLUMN1 FROM TABLE B)
But I need it to look at 2 columns rather than 1. It needs to Select rows no row in TABLE_B has those 2 values together.
Where (NOt Column1 IN (Select ..) Or Not Column2 IN (Select ..))
Or
Where NOt Column1 IN (Select ..) And Not Column2 IN (Select ..)
If I understood the question right, this should work:
select COLUMN1, COLUMN2, COLUMN3
from TABLE_A
left outer join TABLE_B
on TABLE_A.COLUMN1 = TABLE_B.COLUMN1
and TABLE_A.COLUMN2 = TABLE_B.COLUMN2
where TABLE_B.COLUMN1 is null
This is under the assumption that the columns involved in the left outer join do not allow null values. If there can be nulls involved it gets more complicated...