Make rownum value null in the same values - sql

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

Related

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

Query to find the percentage difference of each row in sql server

I have a table with some columns in it. I would like to write a query that iterates through each row and find the total count of all rows that match a column in the selected row and also find the count of all rows that match 2 columns. With these 2 values, I would like to find the percentage difference and print them as column1, percentage(query1(column2)/query2(column2 and column3)).
Below is the query which I wrote
SELECT DISTINCT (t2.column1)
,(
SELECT count(DISTINCT column2)
FROM table1 t1
WHERE t1.column1 = t2.column1
ORDER BY column2
) AS total_count
,(
SELECT count(DISTINCT column2)
FROM table1 t1
WHERE t1.column1 = t2.column1
AND column3 IN (
10
,20
)
ORDER BY column1
,column2
,column3
) AS column3_count
FROM table1 t2;
The above query works but takes a lot of time to process.
I want it as
SELECT DISTINCT (column1)
,percentage(query1 that matches ALL rows WITH column1 / query2 that match ALL rows WITH column1
AND SOME other CONSTRAINT)
FROM TABLE t1
I would like to optimize the above query too. Please let me know
Thanks
I think you just want conditional aggregation. For the counts:
select t1.column1,
count(distinct column2) as num_column2,
count(distinct case when column3 in (10, 20) then column2 end) as num_column2_column3
from table1 t1
group by t1.column1;
I don't understand the calculation for the percentage, but it would seem to be based on these numbers.
select t1.column1,
count(distinct column2) as num_column2,
count(distinct case when column3 in (10, 20) then column2 end) as num_column2_column3
from table1 t1
group by t1.column1;

SQL Server - improve performance of searching a values in table

I'm facing with problem in one query. The easiest will be to explain step by step:
At first I'm searching a specific values in colum1 in table1 by using query like this:
Query #1:
select column1
from table1
where column1 in('xxx','yyy','zzz')
group by column1
having count(*) >3
So now I have a list on values from column1, which occurs more than 3 times.
Then I need to use that list in where condition in another query:
select column1, column2, column3
from table1
where column1 in (query 1)
Unfortunately when I'm using query 1 as subquery, execution is really slow and I need to find a different way to this. Any suggest how can I increase a performance ?
Best regards and thank you in advance
If they are the same table, then use window functions:
select t.*
from (select t.*, count(*) over (partition by column1) as cnt
from table1 t
where column1 in ('xxx', 'yyy', 'zzz')
) t
where cnt > 3;
Both this an your original query will benefit from h having an index on table1(column1).
1)First of all take a look if the query is correctly indexed.
Maybe you have to add an index on column1.
2) try with it:
select column1, column2, column3
from table1 as T1 inner join (
select column1, column2, column3
from table1
where column1 in (query 1)) as T2
on t1.column1 = t2.column1

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