how to update all rows except first? - sql

I have this sql query :
update CCUSTOMERINFO set VALIDTO=sysdate where (
select * from (
select row_number() over (order by created desc) rn, customer_id, CCUSTOMERINFO.VALIDTO
from CCUSTOMERINFO
where customer_id=100309772 order by created DESC) where rn > 1);
But it say it have some mistake.
This query returns all i want to update :
select * from (
select row_number() over (order by created desc) rn, customer_id, CCUSTOMERINFO.VALIDTO
from CCUSTOMERINFO
where customer_id=100309772 order by created DESC) where rn > 1)
Any suggestion how can i do that?

Use it like the below
update CCUSTOMERINFO set VALIDTO=sysdate where rowid in (
select row_id from (
select row_number() over (order by created desc) rn, customer_id, rowid row_id,
CCUSTOMERINFO.VALIDTO
from CCUSTOMERINFO
where customer_id=100309772 order by created DESC) where rn > 1);

Related

Filtering for MAX Beginning Date

I am currently getting the output of the image below. I want to be able to retrieve the latest Turn Time. Essentially the MAX beginning date and MAX end date. How Should I structure my query ?
I think you just want order by:
select top (1) t.*
from t
order by enddate desc, beginning_date desc;
If you want this per id, then you can use window functions or top (1) with ties:
select top (1) t.*
from (select t.*,
row_number() over (partition by id order by enddate desc, beginning_date desc) as seqnum
from t
) t
where seqnum = 1;
You can use row_number()
select * from
(
select *,row_number() over(parition by id order by beginningdate desc) as rn
from tablename
)A where rn=1
For the larger turn time -
select * from
(
select *,row_number() over(parition by id order by turntime desc) as rn
from tablename
)A where rn=1

Max and Min row numbers from single cte code block

;with cte1 as
( select id,
row_number() over (partition by pk,pp,sn order by id asc)
as rn
from mqms_production
) select * into #M from cte1 where rn=1
With the above, I get all the rows with rn=1 but I also want to copy to another table all the rows with max rn for a given partition pk,pp, sn.
Is it possibleto do it without having to write the cte block again with
(partition by pk,pp,sn order by id DESC)
thanks!
You can just add another window function based expression there with reverse sort order and get the top rows on both of them
with cte1 as (
select id,
row_number() over (partition by pk,pp,sn order by id asc) as rn1,
row_number() over (partition by pk,pp,sn order by id desc) as rn2
from mqms_production
)
select * from cte1
where rn1 = 1 or rn2 = 1;

Select only 20 rows of every distinct name

I have a table in which I have over 1000+ rows, in which there is a column "AnaId", values of this column are repeated many times like name 003912 is repeated 85 times, name 003156 in repeated 70 time, I want to select maximum 20 rows of every distinct AnaID. I have no idea how to do it.
SELECT dbo.Analysis.AnaId, Analysis.CasNo, MoleculeId,
SUM(dbo.AnalysisSummary.Area) as TotalArea
FROM dbo.Analysis LEFT JOIN dbo.AnalysisSummary
ON dbo.AnalysisSummary.AnaId = dbo.Analysis.AnaId
WHERE dbo.Analysis.Sample like '%Oil%'
GROUP BY dbo.Analysis.AnaId,Analysis.CasNo, MoleculeId ORDER BY
TotalArea DESC
You can use row_number():
select t.*
from (select t.*, row_number() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
With the edits to your question, you can do:
with t as (
<your query here without order by>
)
select t.*
from (select t.*, row_number() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
If you have another table of names, you can also use cross apply:
select t.*
from names n cross apply
(select top 20 t.*
from t
where t.name = n.name
) t;
Using Rank()
select t.*
from (select t.*, rank() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
Using Dense_Rank()
select t.*
from (select t.*, Dense_Rank() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
Using Row_Number
select t.*
from (select t.*, row_number() over (partition by name order by name) as seqnum
from t
) t
where seqnum <= 20;
This will help uunderstand usage of each Special Functions
Base Code Credits:-#gordon

How to select both row_number and count over partition?

I need to find duplicate record (with master record id and duplicate record ids):
select ciid, name from (
select ciid, name, row_number() over (
partition by related_id, name order by updatedate desc) rn
) where rn = 1;
This gives me the master record IDs, but it also includes records without duplicates.
If I use
select ciid, name from (
select ciid, name, row_number() over (
partition by related_id, name order by updatedate desc) rn
) where rn > 1;
This gets me all the duplicate records, but not the master record.
I was wishing if I do something like:
select ciid, name from (
select ciid, name, row_number() over (
partition by related_id, name order by updatedate desc
) rn, count(*) over (
partition by related_id, name order by updatedate desc
) cnt
) where rn = 1 and cnt > 1;
But I was worried about the performance, or even is it actually doing what I want.
How do I get the master record only for the ones with duplicates? Please note that name is not unique column. Only ciid is unique.
I ended up using similar query in my question:
select ciid, name from (
select ciid, name, row_number() over (
partition by related_id, name order by updatedate desc
) rn, count(*) over (
partition by related_id, name desc
) cnt
) where rn = 1 and cnt > 1;
Works surprisingly well. The master record is where rn = 1 and duplicates are where rn > 1. Make sure count(*) over (partition ..) cannot have order by clause.
I haven't tested this (because I don't have real data and am too lazy to create some), but it seems something along these lines might work:
with has_duplicates as (
select related_id, name
from yourtable
group by related_id, name
having count (*) > 1
),
with_dupes as (
select
y.ccid, y.name,
row_number() over (partition by y.related_id, y.name order by y.updatedate desc) rn
from
yourtable y,
has_duplicates d
where
y.related_id = d.related_id and
y.name = d.name
)
select
ccid, name
from with_dupes
where rn = 1
select ciid, name
from (
select ciid, name,
dense_rank() over (partition by related_id, name order by updatedate desc) rn
from tablename) t
group by ciid,name
having count(distinct rn) > 1;
Edit: To find duplicates, why not just do this.
select x.ciid, x.name, x.updatedate
from tablename x join
(
select name, related_id, max(updatedate) as mxdt, count(*)
from tablename
group by name, related_id
having count(*) > 1
) t
on x.updatedate = t.mxdt and x.name = t.name
You can do a group by with having to select only those id's having more than one row with the same row number.

How to select distinct records based on condition

I have table of duplicate records like
Now I want only one record from duplicate records which has latest created date as How can I do it ?
use row_number():
select EnquiryId, Name, . . .
from (select t.*,
row_number() over (partition by enquiryID order by CreatedDate desc) as seqnum
from table t
) t
where seqnum = 1;
Use ROW_NUMBER function to tag the duplicate records ordered by CreatedDate, like this:
;with CTE AS (
select *, row_NUMBER() over(
partition by EnquiryID -- add columns on which you want to identify duplicates
ORDER BY CreatedDate DESC) as rn
FROM TABLE
)
select * from CTE
where rn = 1