oracle query for no data - sql

I have table A with col1 ,col2 with data as
col1 col2
-----------
1 x
2 x
3 x
1 y
2 y
3 y
4 y
1 z
2 z
I want output as:
col1 col2
-----------
1 x
2 x
3 x
4 x
1 y
2 y
3 y
4 y
1 z
2 z
3 z
4 z
Even if values are not there in col2 for max value in col1 i.e '4' query should display up to 4.

SELECT A.col1, B.col2
FROM (SELECT DISTINCT col1 FROM YourTable) A
CROSS JOIN (SELECT DISTINCT col2 FROM YourTable) B

If you want the cartesian product of each possible combination of values in col1 and col2:
Select col1, col2 from
(select distinct col1 from sourcetable) as t1
Cross join
(select distinct col2 from sourcetable) as t2

Related

drop duplicates on some columns and keep other columns values

I have the following table with Postgres:
Id Col1 Col2 Col3
1 A 1 x
2 A 0 y
3 A 0 z
4 B 0 x
5 B 1 y
6 C 0 z
As part of a select query, I want to be able to drop duplicates in Col1, based on the highest Col2 values (where will never be multiple highest values per Col1 value), and keep the corresponding Col2, Col3 values.
Desired output:
Id Col1 Col2 Col3
1 A 1 x
5 B 1 y
6 C 0 z
In Postgres, you can use distinct on:
select distinct on (col1) t.*
from t
order by col1, col2 desc;

Filter in SQL on distinct values after grouping

I have a dataset like
col1 col2 col3
A x 1
A x 2
A x 3
B y 4
B -y 5
B y 6
C -z 7
C z 8
C -z 9
D t 10
D t 11
D t 12
how can i pick out just the groups from col1 that have distinct values in col2? So A,D in this case.
something like
select * from table t1
where (select count(distinct col2)
from table t2
where t1.col1 = t2.col1) > 1
but more optimized?
If all you need is the column col1 you can group by col1 and set the condition in the HAVING clause:
SELECT col1
FROM tablename
GROUP BY col1
HAVING COUNT(DISTINCT col2) = 1;
If you want all the rows from the table use the above query with the operator IN:
SELECT *
FROM tablename
WHERE col1 IN (
SELECT col1
FROM tablename
GROUP BY col1
HAVING COUNT(DISTINCT col2) = 1
)
You can use group by and having:
select col1
from t
group by col1
having min(col2) <> max(col2);

PostgreSQL unnest(array_agg(x))

Lets say we have a table 1
1 2 3
a x 10
a y 20
b z 50
As result of the select we want to get the following:
1 2 3
a x 30
a y 30
b z 50
At least the sum of the lines where column 1 is equal. I do the following select and it is working. But the select looks ugly, is there a smarter solution?
SELECT 1, UNNEST(ARRAY_AGG(2)), SUM(3) FROM table1
GROUP BY (1)
You can do a window sum instead:
select col1, col2, sum(col3) over(partition by col1) col3
from mytable

How to write the below SQL queries?

Consider 3 columns like below. I need to get columns having same col1 with col2 values as 1 and 2 and col3 have 2 different values for col2 where col1 will be same for col2 and col3
Col1 Col2 Col3
A 1 IND
A 2 IND
A 3 IND
B 1 IND
B 2 PAK
B 3 IND
B 4 IND
C 1 IND
C 2 IND
C 3 PAK
C 4 PAK
D 1 IND
D 2 PAK
E 1 PAK
E 2 SA
The result will be as given below
Col1 Col2 Col3
B 1 IND
B 2 PAK
D 1 IND
D 2 PAK
E 1 PAK
E 2 SA
Here is what I tried for col1 and col2:
select col1 from your_table
where col2 in (1,2)
group by col1
having count(distinct col2) > 1
The rows with 3 and 4 in Col2 can be ignored as per your request so
Self Join on col1
Filter to col2 in (1, 2)
col3 is different
Like this
SELECT
*
FROM
MyTable M1
JOIN
MyTable M2 ON M1.COl1 = M2.COl1
WHERE
M1.Col2 IN (1, 2)
AND
M2.Col2 IN (1, 2)
AND
M2.Col3 <> M1.COl3
One approach to this is aggregation. The following gets the column A values that meet your conditions:
select col1
from t
where col2 in (1, 2)
group by col1
having min(col3) <> max(col3);
If you want to get the original rows, there are multiple ways. Apart from obvious ones (such as in, exists, and join), you can use window functions:
select col1, col2, col3
from (select t.*,
min(col3) over (partition by col1) as mincol3,
max(col3) over (partition by col1) as maxcol3
from t
where col2 in (1, 2)
) t
where mincol3 <> maxcol3;

Query without Union operator SQL

TABLE X
col1,col2
1 , 2
1 , 7
1 , 4
1 , 8
2 , 3
2 , 1
2 , 2
3 , 1
3 , 8
3 , 9
3 , 4
4 , 5
4 , 3
4 , 2
4 , 8
4 , 4
I want to retrieve the col1 values that contains in the col2 the values 2 and 4
in this case it will retrieve the values 1 and 4
How can i accomplish this without using the UNION ALL operator ?
The query that i am using is
select distinct col1
from X as A
where col1 = (
select col1 from (
select distinct col1
from X as B
where A.col1 = B.col1 and col2 = 2
union ALL
select distinct col1
from X as C
where A.col1 = C.col1 and col2 = 4
) D
group by col1
having count(col1) > 1
)
It is returning the correct result but i guess is to performance expensive.
Can anyone give me ideas about how to achieve the same result but without unions ?
This problem is called Relational Division, here is one way to do so:
SELECT col1
FROM tablex
WHERE col2 IN (2, 4)
GROUP BY col1
HAVING COUNT(DISTINCT col2) >=2
The HAVING COUNT(col2) >=2 will ensure that the selected col1 must have both the two values 2 and 4 at least.
SQL Fiddle Demo
I think the best performance will come from inner joining the table with itself:
SELECT DISTINCT X1.col1
FROM X X1 INNER JOIN X X2 ON X1.col1=X2.col1
WHERE X1.col2=2 AND X2.col2=4