SQL query to simulate distinct - sql

SELECT DISTINCT col1, col2 FROM table t ORDER BY col1;
This gives me distinct combination of col1 & col2. Is there an alternative way of writing the Oracle SQL query to get the unique combination of col1 & col2 records with out using the keyword distinct?

Use the UNIQUE keyword which is a synonym for DISTINCT:
SELECT UNIQUE col1, col2 FROM table t ORDER BY col1;

I don't see why you would want to but you could do
SELECT col1, col2 FROM table_t GROUP BY col1, col2 ORDER BY col1

Another - yet overly complex and somewhat useless - solution:
select *
from (
select col1,
col2,
row_number() over (partition by col1, col2 order by col1, col2) as rn
from the_table
)
where rn = 1
order by col1

select col1, col2
from table
group by col1, col2
order by col1
or a less elegant way:
select col1,col2 from table
UNION
select col1,col2 from table
order by col1;
or a even less elegant way:
select a.col1, a.col2
from (select col1, col2 from table
UNION
select NULL, NULL) a
where a.col1 is not null
order by a.col1

Yet another ...
select
col1,
col2
from
table t1
where
not exists (select *
from table t2
where t2.col1 = t1.col1 and
t2.col2 = t1.col2 and
t2.rowid > t1.rowid)
order by
col1;

Variations on the UNION solution by #aF. :
INTERSECT
SELECT col1, col2 FROM tableX
INTERSECT
SELECT col1, col2 FROM tableX
ORDER BY col1;
MINUS
SELECT col1, col2 FROM tableX
MINUS
SELECT col1, col2 FROM tableX WHERE 0 = 1
ORDER BY col1;
MINUS (2nd version, it will return one row less than the other versions, if there is (NULL, NULL) group)
SELECT col1, col2 FROM tableX
MINUS
SELECT NULL, NULL FROM dual
ORDER BY col1;

Another ...
select col1,
col2
from (
select col1,
col2,
rowid,
min(rowid) over (partition by col1, col2) min_rowid
from table)
where rowid = min_rowid
order by col1;

Related

Delete Duplicate record in sql server if 2 colums matching

Col1
Col2
Col3
A
B
1
A
B
1
A
B
2
A
B
2
A
c
1
When col1 and Col2 values are same and Col3 values are different I dont want that values in result set.
I want result as below. I tried with row_number, group by , so manythings but did not worked. Please help me here
Col1
Col2
Col3
A
c
1
You can use exists:
delete from t
where exists (select 1
from t t2
where t2.col1 = t.col1 and t2.col2 = t.col1 and
t2.col3 <> t.col3
);
You can also use window functions:
with todelete as (
select t.*,
min(col3) over (partition by col1, col2) as min_col3,
max(col3) over (partition by col1, col2) as min_col4
from t
)
delete from todelete
where min_col3 <> max_col3;
Best way is to make these column a unique composite key. But here is a query to delete all records other than your desired result.
delete from Table_1
where
Col1=(SELECT Col1
FROM table_1
GROUP BY Col1, Col2
HAVING Count(*) > 1)
And
Col2 =(SELECT Col2
FROM table_1
GROUP BY Col1, Col2
HAVING Count(*) > 1)
this might not be the most optimized and efficient query but it works. if you don't want to delete duplicated records and just retrieve unique ones:
SELECT Col1,Col2
FROM table_1
GROUP BY Col1, Col2
HAVING Count(*) = 1
To get duplicating records:
SELECT Col2,Col1
FROM table_1
GROUP BY Col1, Col2
HAVING Count(*) > 1

How do I SELECT two distinct columns?

I want to be able to select two distinct from col1 and col2 ordered by id.
I'm struggling to do this because when I write the following SQL query...
SELECT DISTINCT col1, col2
FROM table
ORDER BY id
I can't ORDER BY id because it's not in the SELECT statement but if I put id in the SELECT statement it will take the DISTINCT id, col1 and col2. Which is basically the whole table as it is since the id column is unique.
How do I do this?
You can use aggregation, and put an aggregate function in the order by clause:
select col1, col2 from mytable group by col1, col2 order by min(id) limit 10
This is one way to do it:
select A.col1, A.col2
from
(select id, col1, col2
from Tablet
order by id) A
left join
(select min(id) id2, col1, col2
from Tablet
GROUP BY COL1, COL2) B
on A.COL1 = B.COL1 AND A.COL2=b.COL2
where A.id = B.id2
LIMIT 4;
Here is the DEMO

Oracle: Alternative to sub-query

Is there an alternative to re-write the below oracle query without using sub-queries
SELECT COL1,COL2 FROM TABLE WHERE COL2 IN (SELECT MAX(COL2) FROM TABLE)
Edit: There is only 1 table with COL1 and COL2 where the row with maximum value of
COL2 is the expected output
SELECT COL1,COL2
FROM TABLE
ORDER BY COL2 DESC
FETCH FIRST 1 ROW WITH TIES
This one should also work:
SELECT MAX(COL1) KEEP (DENSE_RANK LAST ORDER BY COL2) as COL1,
MAX(COL2) as COL2
FROM TABLE;
Use PARTITION key find out maximum col2 with col1 as per below:
select COL1, COL2 from (
select COL1, COL2, ROW_NUMBER() over(PARTITION BY COL1 ORDER BY COL2 desc) row_num from TABLE
) where row_num=1;
Assuming COL1 can be used as candidate key -
SELECT T1.COL1,
T1.COL2
FROM TABLE1 T1
INNER JOIN TABLE1 T2
ON (T1.COL1 = T2.COL1
AND T1.COL2 >= T2.COL2)

Dynamic Group By in a Query

Is there a way to apply or not a group by into a query? for example, I have this:
Col1 Col2 Col3
A 10 X
A 10 NULL
B 12 NULL
B 12 NULL
I have to group by Col1 and Col2 only when I have a value in Col3, if Col3 is null, I don't need to group it. The result should be:
Col1 Col2
A 20
B 12
B 12
Maybe is not an elegant example, but this is the idea.
Thank you.
Here's a SQL Fiddle that does what you want:
http://sqlfiddle.com/#!3/b7f07/2
Here's the SQL itself:
SELECT col1, sum(col2) as col2 FROM dataTable WHERE
col1 in (SELECT col1 from dataTable WHERE col3 IS NOT NULL)
GROUP BY col1
UNION ALL
SELECT col1, col2 FROM dataTable WHERE
(col1 not in
(SELECT col1 from dataTable WHERE col3 IS NOT NULL and col1 is not null))
It sounds like you want all unique values of col1 when col3 is not null. Otherwise, you want all values of col1.
Assuming you have a SQL engine that supports window functions, you can do this as:
select col1, sum(col2)
from (select t.*,
count(col3) over (partition by col1) as NumCol3Values,
row_number() over (partition by col1 order by col1) as seqnum
from t
) t
group by col1,
(case when NumCol3Values > 1 then NULL else seqnum end)
The logic is pretty much as you state it. If there is any non-NULL value, then the second clause of the group by always evaluates to NULL -- everything goes in the same group. If things are all NULL, then the clause evaluates to a sequence number, which puts each values on a separate row.
This is a bit more difficult without window functions. If I assume that the minimum value of column 3 (when not NULL) is unique, then the following would work:
select t.col1,
(case when minCol3 is null then tsum.col2 else t.col2 end) as col2
from t left outer join
(select col1, sum(col2) as col2,
min(col3) as minCol3
from t
) tsum
on t.col1 = tsum.col1
where minCol3 is NULL or t.col3 = MinCol3
re: Is there a way to apply or not a group by into a query?
Not directly, but you can break it down by groupings and then UNION the results together.
Does this work?
Select col1, sum(col2)
from table
group by col1, col2
having max(col3) is not null
union all
select col1, col2
from table t left outer join
(Select col1, col2
from table
group by col1, col2
having max(col3) is not null) g
where g.col1 is null

How to "HAVING COUNT(DISTINCT(col1, col2))"

So I have a table with three columns - col1, col2 and col3. I need to select those values of col1 that share rows with only one combinarion of col2 and col3. In ideal world I would write this:
SELECT col1 FROM table
GROUP BY col1
HAVING COUNT(DISTINCT(col2, col3)) = 1
How to do that in the real world?
So far I have two solutions - group by col1 and col2 and by col1 and col3 them join results; or group by all three then group that by col1. Unfortunately I get (very) different wor counts.
The database is on SQL Server 2005.
SELECT col1
FROM table
GROUP BY col1
HAVING MAX(col2) = MIN(col2) AND MAX(col3) = MIN(col3)
More complex:
SELECT col1
FROM
(
SELECT
col1,
ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2, col3) as rn
FROM table
) T
GROUP BY col1
HAVING MAX(rn) = 1
select *
from mycols
where col1 in (
select max(col1)
from mycols
group by col2, col3
having count(col1)=1
)