Removing Partitioned rows from oracle sql query output - sql

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);

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.

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
);

Make rownum value null in the same values

I have the sql code and i want for every unique value from COLUMN1 the same rownum.
For example in the example i want null values for rownum 2,3 and for column 2 rownum 2
select rownum,
t1.column1 as column1,
t1.Column2 as column2,
t3.Column3 as column3
from Table1 t1,Table3 t3,Table2 t2
where t3.S_ID=t2.AS_ID
and t2.KT_ID=t1.T_ID
How can i implement this?
First, learn proper explicit join syntax. Second, you can readily do what you want using lag() and other analytic functions:
select (case when column1 = lag(column1) over (order by column1, column3)
then NULL
else dense_rank() over (order by column1)
end) as rn,
t1.column1 as column1,
t1.Column2 as column2,
t3.Column3 as column3
from Table1 t1 join
Table2 t2
on t2.KT_ID = t1.T_ID join
Table3 t3
on t3.S_ID = t2.AS_ID
order by column1, column3;
Some notes:
SQL queries return unordered result sets. If you want rows in a particular order -- or even in the same order the next time you run the query -- then include an order by.
I arbitrarily added column3 to the ordering. It can be any column that makes the sort stable. That is, each row has a unique set of order keys, so they are in the same order each time.
The same ordering conditions are used for the lag() functions, but only column1 is used for the dense_rank().
Learn explicit join syntax. It is more powerful, and almost everyone thinks it is easier to read.
select
case when row_number() -- if it's the first row per group...
over(partition by column1
order by column3) = 1
then dense_rank() -- ... return 1,2,3
over(order by column1)
else null
end,
t1.column1 as column1,
t1.Column2 as column2,
t3.Column3 as column3
from Table1 t1,Table3 t3,Table2 t2
where t3.S_ID=t2.AS_ID
and t2.KT_ID=t1.T_ID
This might help you...
select rownum,column1,column2,column3 from (
Select rownum,column1,column2,column3,
row_number() over( partition by column1,column2 order by column1,column2) as analytic_rnm
from(
select rownum,
column1 as column1,
Column2 as column2,
Column3 as column3
from Table1 t1,Table3 t3,Table2 t2
where t3.S_ID=t2.AS_ID
and t2.KT_ID=t1.T_ID
)X
)M
where analytic_rnm=1
union all
select NULL as rownum,
column1,column2,column3 from (
Select rownum,column1,column2,column3,
row_number() over( partition by column1,column2 order by column1,column2) as analytic_rnm
from(
select rownum,
column1 as column1,
Column2 as column2,
Column3 as column3
from Table1 t1,Table3 t3,Table2 t2
where t3.S_ID=t2.AS_ID
and t2.KT_ID=t1.T_ID
)X)Y
where analytic_rnm>1

Duplicates 101 from basic search to delete?

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

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