Duplicates 101 from basic search to delete? - sql

Goal is to find duplicates.
Select Column1, Column2, Column3
from Tablename
where Column1 = 1111 and Column2 = 2222
group by Column1, Column2, Column3
having count(*) > 1
This select query finds all the rows that are duplicates. I want to delete them all so I changed select to delete:
Delete from Tablename
where Column1 = 1111 and Column2 = 2222
group by Column1, Column2, Column3
having count(*) > 1
I get an error that says I can't use "group by".
What is another option to delete them all?

Try this query:
with v1 as
(select
ROW_NUMBER() OVER (ORDER BY Column1) AS ID,t1.*
FROM Tablename t1)
DELETE FROM v1 where Column1=1111 and Column2=2222
and id not in (select min(id) from v1 group by
Column1, Column2, Column3);
SQL Fiddle

Related

Union in sql with default return

I have scenarios where there are multiple tables Table1, Table2, and Table3 and there are some common columns in them. Now I have to take join with tables on bases of the condition if record exists from the table than its good but if it not exist then it doesn't return any row but I have to return some default/0
select 'Section','Table1',column1, column2, column3 from table1 where column>1
union
select 'Section','Table2',column1, column2, column3 from table2 where column>3
union
select 'Section','Table3',column1, column2, column3 from table3 where column>2
suppose data doesn't exist in table 2 instead of skipping that table record should show in the result
in simple I want if the record not exist against any table it would be replaced by the below code
select 'Section','Table2',0 as column1, 0 as column2, 0 as column3
Output should be like this
Results
Section Table1 2 2022-06-12 abc
Section Table2 0 '' ''
Section Table3 3 2022-07-22 Xyz
You can use EXISTS. ie:
select 'Section','Table1',column1, column2, column3
from (values (0,0,0))
t(column1,column2,column3)
where not exists (select * from table1 where column1 > 1)
union
select 'Section','Table1',column1, column2, column3 from table1 where column1>1
union
select 'Section','Table2',column1, column2, column3
from (values (0,0,0))
t(column1,column2,column3)
where not exists (select * from table2 where column1 > 3)
union
select 'Section','Table2',column1, column2, column3 from table2 where column1>3
union
select 'Section','Table3',column1, column2, column3
from (values (0,0,0))
t(column1,column2,column3)
where not exists (select * from table3 where column1 > 2)
union
select 'Section','Table3',column1, column2, column3 from table3 where column1>2;
DBFiddle demo
It is SQL server but is valid for many databases if not all.

Removing Partitioned rows from oracle sql query output

I have below query
SELECT ROW_NUMBER() OVER ( PARTITION BY COLUMN1, COLUMN2, COLUMN3 ORDER BY COLUMN1, COLUMN2) AS ROW_NUM, COLUMN1, COLUMN2, COLUMN3
FROM (SUBQUERY)
GROUP BY COLUMN1, COLUMN2, COLUMN3
OUTPUT of above query:-
I need to perform something equivalent to
IF (COLUMN2 == 'PQR' AND COLUMN3 IS NOT NULL)
THEN
"Delete whole partition from output having value A3 in column1"
Explaination:-
If COLUMN2 is having value PQR and COLUMN3 is having any DATE_TIME (i.e. NOT NULL) then all the corresponding COLUMN1 value should not be present in output of query.
OUTPUT required is:-
I tried to be as clear as I can be. Let me know if I need to clarify my question more.
NOTE:- I want to remove those rows only from output of the query not from actual table.
If you are doing this using a subquery, then you might want to use window functions:
SELECT s.*
FROM (SELECT ROW_NUMBER() OVER ( PARTITION BY COLUMN1, COLUMN2, COLUMN3 ORDER BY COLUMN1, COLUMN2) AS ROW_NUM,
COLUMN1, COLUMN2, COLUMN3,
COUNT(CASE WHEN COLUMN2 = 'PQR' THEN COLUMN3 END) OVER (PARTITION BY COLUMN1) as cnt
FROM (SUBQUERY)
GROUP BY COLUMN1, COLUMN2, COLUMN3
) s
WHERE cnt = 0;
This counts the number of COLUMN3 values where COLUMN2 = 'PQR' over all each COLUMN1. It then returns only the rows where this count is 0.
The advantage of this approach is that it only evaluates the subquery once -- that can be a performance win (over NOT EXISTS) if it is complicated.
If you want a select query then you can use NOT EXISTS:
SELECT * FROM YOUR_TABLE T1
WHERE NOT EXISTS (SELECT 1 FROM YOUR_TABLE T2
WHERE T1.COLUMN1 = T2.COLUMN1
AND T2.COLUMN2 = 'PQR' AND T2.COLUMN3 IS NOT NULL);
You can use the EXISTS to delete such records as follows:
DELETE FROM YOUR_TABLE T1
WHERE EXISTS (SELECT 1 FROM YOUR_TABLE T2
WHERE T1.COLUMN1 = T2.COLUMN1
AND T2.COLUMN2 = 'PQR' AND T2.COLUMN3 IS NOT NULL);

Select row after filter row has a coincident column in sql

I have a database as below
Column1 column2 column3
A123 abc Def
A123 xyz Abc
B456 Gh Ui
I want to select rows which don't have coincident content in column 1 by sql command.
In this case, The expected result is only row 3rd.
How to do it?
Thanks
you could use a join with a subselect for count =1
select * from my_table m
inner join (
select column1, count(*)
from my_table
group by column_1
having count(*) =1
) t on t.column_1 = m.column_1
WITH CTE AS (Select COUNT(Column1) OVER(PARTITION BY Column1 ) as coincident,* from table )Select * from CTE where coincident =1
I would use window functions:
select Column1, column2, column3
from (select t.*, count(*) over (partition by column1) as cnt
from t
) t
where cnt = 1;
However, there are other fun ways. For instance, aggregation:
select column1, max(column2) as column2, max(column3) as column3
from t
group by column1
having count(*) = 1;
Or if you know one of the other columns is going to have different values on different rows, then not exists may be the most efficient solution:
select t.*
from t
where not exists (select 1
from t t2
where t2.column1 = t.column1 and
t2.column2 <> t.column2
);

Return column with running sequence number Oracle

My simple query returns data like this:
SELECT column1, column2 FROM table1
COLUMN1 COLUMN2
------- -------
CA A
CA B
CB C
CB D
I want to return column3 with these values (for same COLUMN1 value, I want to return same sequence number):
COLUMN3
-------
1
1
2
2
You can use analytic function DENSE_RANK.
SELECT column1,
column2,
DENSE_RANK() OVER(ORDER BY column1) as "column3"
FROM table1
See the following for some examples - oracle-base.com/articles/misc/rank-dense-rank-first-last-analytic-functions.php#dense_rank
Try this query,
Select column1, column2,
dense_rank() over (order by column1) as column3
from table1;

How to access the value of a function generated column in SQL

I have the following SQL
select count(*) col, column1, column2, column3 from TempTable
group by column1, column2, column3
order by 1 desc
so the column generated by the count will return a number and there are 17 rows that do not have the number 1 (duplicate rows as columns 1, 2 and 3 are primary keys) and i want to delete any that have the count greater than 1?
You can use the having-clause:
select count(*) col, column1, column2, column3
from TempTable group by column1, column2, column3
having count(*) > 1
order by 1 desc
To delete:
delete tt
from TempTable tt
inner join (select count(*) col, column1, column2, column3
from TempTable group by column1, column2, column3
having count(*) > 1) tmp
on tmp.column1 = tt.column1
and tmp.column2 = tt.column2
and tmp.column3 = tt.column3
First you insert the data in temporary table:
select count(*) col, column1, column2, column3
into #temp
from TempTable group by column1, column2, column3 order by 1 desc
Then, you delete the data, and insert it from the #temp table:
delete from TempTable
go
insert into TempTable select column1, column2, column3 from #temp
go