Sql query to group by and merge rows - sql

I am working on sql query with table structure like below
col1 col2 col3
1 nik NULL
1 nik1 NULL
1 NULL mah
1 NULL mah1
Now i want output like
col1 col2 col3
1 nik mah
1 nik1 mah1
So i want to merge null values if there is value in col2 or col3
How can i achieve this ??
EDIT :Main structure is if col2 has values then col3 will be null and if col3 has value then col2 will be null
So i want to reduce the total no of rows by filling up null values

Try this:
SELECT T1.Col1,T1.Col2,T2.Col3
FROM
(SELECT Col1,Col2,ROW_NUMBER()OVER(ORDER BY Col1) as RN
FROM TableName
WHERE Col2 IS NOT NULL) T1 FULL OUTER JOIN
(SELECT Col1,Col3,ROW_NUMBER()OVER(ORDER BY Col1) as RN
FROM TableName
WHERE Col3 IS NOT NULL) T2 ON T1.Col1=T2.Col1 AND T1.RN=T2.RN
See result in SQL Fiddle.

Related

How to get Distinct value for a column on the basis of other column in Oracle

I want to get the distinct values from COL1 and it's COL3 value also but the condition is if COL1 = COl2 then it should pick the matching COL3 value otherwise pick the COL1 value if they are not same. I'm stuck in the logic, any help will be appreciated!
Please see the below image for more detail:
select DISTINCT COL1,
CASE WHEN COL1 = COL2 THEN COL3 END COL3 from TABLE1
WHERE COL1 IS NOT NULL;
Do a GROUP BY to get distinct COL1 values.
Use COALESCE() to return the COL3 value if there exists a COL1 = COL2 row, otherwise return the max COL3 value for the COL1. (Could use MIN() too, if that's better.)
select COL1,
COALESCE( MAX(CASE WHEN COL1 = COL2 THEN COL3 END), MAX(COL3) )
FROM table1
WHERE COL1 IS NOT NULL
GROUP BY COL1
use correlated subquery
select col1,col3
from TABLE1 a
where col2 in (select min(col2) from table1 b where a.col1=b.col1)
select distinct COL1, if(COL1 = COL2, COL3, COL1) as result
from table1
I think that you can join the table with itself and then use a join conditio to filter that out, then decide in select wether there was COL2 = COL1 and choose appropriate COL3:
SELECT DISTINCT a.COL1, CASE WHEN b.COL1 IS NULL THEN a.COL3 ELSE b.COL3 END as COL3
FROM TABLE1 a
LEFT JOIN TBALE2 b
on a.COL1 = b.COL2
and a.COL1 = b.COL1
This way you have on table a all the data, and on table b data if and only if COL1 matches with COL2. Then you select whichever COL3 is not null, prefarably the one from table b. There is Oracle function coalesce that does just that.
With a self join:
select distinct
t.col1,
case
when tt.col1 is null then t.col3
else tt.col3
end col3
from tablename t left join tablename tt
on tt.col1 = t.col1 and tt.col2 = t.col1
See the demo.
Results:
> COL1 | COL3
> ---: | :---
> 11 | ABC
> 12 | ABC
> 13 | BDG
> 14 | DEF
> 15 | CEG

How can I get data in single row when multiple columns data have null in some columns?

How can I get data in single row when multiple columns data have null in some columns?
Following is the scenario
col1 col2 col3 col4
----- ------ ---------------
1 NULL NULL NULL
NULL 2 NULL NULL
NULL NULL 3 NULL
NULL NULL NULL 4
I want output like this
col1 col2 col3 col4
----- ------ ---------------
1 2 3 4
You can use aggregate functions as below:
select min(col1) as col1,min(col2) as col2,min(col3) as col3,min(col4) as col4 from t
select max(col1) as col1,max(col2) as col2,max(col3) as col3,max(col4) as col4 from t
select sum(col1) as col1,sum(col2) as col2,sum(col3) as col3,sum(col4) as col4 from t
select avg(col1) as col1,avg(col2) as col2,avg(col3) as col3,avg(col4) as col4 from t
However Min or Max or more meaningful than the Avg and Sum in this scenario.
select max(col1) as col1,
max(col2) as col2,
max(col3) as col3,
max(col4) as col4
from your_table
Try this way.
SELECT DISTINCT
(SELECT TOP 1 Col1 FROM TestTable WHERE Col1 IS NOT NULL) AS 'Column1',
(SELECT TOP 1 Col2 FROM TestTable WHERE Col2 IS NOT NULL) AS 'Column2',
(SELECT TOP 1 Col3 FROM TestTable WHERE Col3 IS NOT NULL) AS 'Column3',
(SELECT TOP 1 Col4 FROM TestTable WHERE Col4 IS NOT NULL) AS 'Column4'
From TestTable
Example 01 
Col1 Col2 Col3 Col4
----- ------ ---------------
1 NULL NULL NULL
NULL 2 NULL NULL
NULL NULL 3 NULL
NULL NULL NULL 4
Result
Column1 Column2 Column3 Column4
-------------------------------
1 2 3 4
Example 02
Col1 Col2 Col3 Col4
----- ------ ---------------
1 NULL NULL NULL
NULL 2 NULL 2
5 NULL 3 NULL
NULL NULL NULL 4
Result
Column1 Column2 Column3 Column4
-------------------------------
1 2 3 2

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;

SQL filtering out less specific rows

My Table data looks like
Col1 | Col2 | Col3
1 | 2 | NULL
1 | 2 | 3
1 | NULL | NULL
1 | 5 | NULL
2 | NULL | NULL
I want to write a query, so that I get only the most specific entries. ie. in the above example row1 is more specific row3 as Value of "Col1" is same in both but Value in "Col2" is more specific( not null) in row1, similarly row2 is more specific than row1.
For the above dataset the result should look like:
Col1 | Col2 | Col3
1 | 2 | 3
1 | 5 | NULL
2 | NULL | NULL
NOTE: Datatype of column can be anything.
I am assuming that the columns are "ordered" as they are in your query, so you don't have a case where col2 is null and col3 is not null:
select col1, col2, col3
from table t
where (col3 is not null) or
(col3 is null and col2 is not null and
not exists (select 1
from table t2
where t2.col1 = t.col1 and t2.col2 = t.col2 and t2.col3 is not null
)
) or
(col2 is null and col1 is not null and
not exists (select 1
from table t2
where t2.col1 = t.col1 and t2.col2 is not null
)
);
The logic behind this is:
Take all rows where col3 is not null.
Take all rows where col2 is not null and there are no similar rows with a value in col3.
Take all rows where col1 is not null and there are no similar rows with a value in col2.
EDIT:
In Oracle, you can do this more simply:
select col1, col2, col3
from (select t.*,
max(col3) over (partition by col1, col2) as maxcol3,
max(col2) over (partition by col1) as maxcol2
from table t
) t
where (col3 is not null) or
(col2 is not null and maxcol3 is null) or
(col1 is not null and maxcol2 is null);
EDIT II:
(With a clarified definition of "more specific".)
I think this is the extrapolation of the logic. It requires looking at all combinations:
select col1, col2, col3
from (select t.*,
max(col3) over (partition by col1, col2) as maxcol3_12,
max(col2) over (partition by col1, col3) as maxcol2_13,
max(col1) over (partition by col2, col3) as maxcol1_23,
max(col1) over (partition by col1) as maxcol1_2,
max(col1) over (partition by col2) as maxcol1_3,
max(col2) over (partition by col1) as maxcol2_1,
max(col2) over (partition by col3) as maxcol2_3,
max(col3) over (partition by col2) as maxcol3_1,
max(col3) over (partition by col2) as maxcol3_2,
from table t
) t
where (col1 is not null and col2 is not null and col3 is not null) or
(col1 is not null and col2 is not null and maxcol3 is null) or
(col1 is not null and col3 is not null and maxcol2 is null) or
(col2 is not null and col1 is not null and maxcol3 is null) or
(col2 is not null and col3 is not null and maxcol1 is null) or
(col3 is not null and col1 is not null and maxcol2 is null) or
(col3 is not null and col2 is not null and maxcol1 is null) or
(col1 is not null and maxcol2 is null and maxcol3 is null) or
(col2 is not null and maxcol1 is null and maxcol3 is null) or
(col3 is not null and maxcol1 is null and maxcol2 is null);
The first combination says "keep this row if all values are not null". The second says: "keep this row if col1 and col2 are not null and col3 never has a value". And so on to the last one that says: "keep this row is col3 is not null and col1 and col2 never have values".
This might simplify to:
where not ((col1 is null and maxcol1 is not null) or
(col2 is null and maxcol2 is not null) or
(col3 is null and maxcol3 is not null)
);
Divide n Conquer kind of Approach!
Demo : SQL Fiddle
SELECT col1,col2,MAX(col3)
FROM test
WHERE col1 is NOT NULL AND col2 is NOT NULL
GROUP BY col1,col2
UNION
SELECT col1,MAX(col2),col3
FROM test
WHERE col1 is NOT NULL AND col3 is NOT NULL
GROUP BY col1,col3
UNION
SELECT MAX(col1),col2,col3
FROM test
WHERE col2 is NOT NULL AND col3 is NOT NULL
GROUP BY col2,col3
UNION
SELECT col1,NULL,NULL
FROM test
GROUP BY COL1
HAVING COUNT(COL2) = 0 AND COUNT(COL3) = 0

SQL Server - Query to return groups with multiple distinct records

My table:
Col1 Col2
1 xyz
1 abc
2 abc
3 yyy
4 zzz
4 zzz
I have a table with two columns. I want to query for records where col1 has more than one DISTINCT col2 values. In the example table given above, the query should return records for col1 with value "1".
Expected query result:
Col1 Col2
1 xyz
1 abc
SELECT *
FROM tableName
WHERE Col1 IN
(
SELECT Col1
FROM tableName
GROUP BY Col1
HAVING COUNT(DISTINCT col2) > 1
)
SQLFiddle Demo
select t.col1, t.col2
from (
select col1
from tbl
group by col1
having MIN(col2) <> MAX(col2)
) x
join tbl t on t.col1 = c.col1