delete duplicate record using rank() function in cte - sql-server-2008

with DeleteDUplicateinXYZ
as
(
Select ID, rank()over( order by Id Asc) as [rank]
from ppp -----------never use 'partion by' while using rank
)Delete from DeleteDUplicateinXYZ
where [rank] in (Select id, count([rank])
from DeleteDUplicateinXYZ group by Id having count([rank]) >=2)

Related

I need to get last created eligible rider ids and pinged rider ids accordeing to a orderId using a sql query

I need to get my data set as this table
I am trying to get eligible set like this, need to group_concat pinged set also
x.id IN (SELECT MAX(x.id) FROM x WHERE ping rider id IS NULL GROUP BY orderId)
You can assign a group based on the cumulative number of non-null values in eligible_riders. Then aggregate and take the last value:
select og.*
from (select order_id, grp, max(eligible_riders) as eligible_riders,
group_concat(rider_id) as riders,
row_number() over (partition by order_id order by min(id) desc) as seqnum
from (select t.*,
sum(eligible_riders <> '') over (partition by order_id order by id) as grp
from t
) t
group by order_id, grp
) og
where seqnum = 1;
Hmmm . . . You could also do this with a correlated subquery, which might look a bit simpler:
select order_id, max(eligible_riders) as eligible_riders,
group_concat(rider_id) as riders
from t
where t.id >= (select max(t2.id)
from t t2
where t2.order_id = t.order_id and
t2.eligible_riders <> ''
)
group by order_id;
For performance, you want an index on (order_id, eligible_riders).

MySQL-ordering partitions randomly

table1 has 3 columns in my database: id, category, timestamp. I need to query the newest 3 rows from each category:
WITH ranked_rows AS
(SELECT t.*, ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS rn
FROM table1 AS t)
SELECT ranked_rows.* FROM ranked_rows WHERE rn<=3
now I need to select 10 partitions from the results randomly (please notice that each partition has 3 rows). how to do that?
There are various methods. One is:
WITH ranked_rows AS (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS seqnum,
DENSE_RANK() OVER (ORDER BY MD5(category)) as catnum
FROM table1 t
)
SELECT ranked_rows.*
FROM ranked_rows
WHERE seqnum <= 3 AND catnum <= 10;
The md5() just makes the results look random.
if you want true random per category, here is one way :
with categorycte as (
select category , rand() randomcatid
from table1
group by category
),ranked_rows AS
(
SELECT t.*
, ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS rn
, dense_rank() over (order by randomcatid) catnum
FROM table1 AS t
join categorycte c on t.category = c.category
)
SELECT ranked_rows.* FROM ranked_rows
WHERE rn<=3 and catnum <= 10;

Get the distinct rows with oldest date

I have a table like this:
MyTable:
id: pk
numero: varchar
data_modif: timestamp
...
I have multiple records with same value in numero and I need to return each distinct numero record with oldest data_modif. How can I do this?
This sounds like aggregation:
select numero, min(data_modif)
from mytable
group by numero;
If you want the entire row, then window functions are one method:
select t.*
from (select t.*,
row_number() over (partition by numero order by data_modif asc) as seqnum
from mytable t
) t
where seqnum = 1;
EDIT:
In an old version of MySQL, you woudl use:
select t.*
from t
where t.data_modif = (select min(t2.data_modif)
from t t2
where t2.numero = t.numero
);

How can i get just the latest 2 records on each group when using GROUP_CONCAT?

SELECT id, GROUP_CONCAT(type SEPARATOR '/') as types FROM `sems` GROUP by year
I just want to get the 2 latest record on each group
If you are running MySQL 8.0, you can use row_number() for this. You need an ordering column to define the latest record, I assumed ordering_id:
select id, group_concat(type order by rn separator '/') types
from (
select id, type, row_number() over(partition by id order by ordering_id desc) rn
from sems
) t
where rn <= 2
group by id
In earlier versions, one option is to filter with a subquery:
select id, group_concat(type order by rn separator '/') types
from sems s
where s.ordering_id >= (
select s1.ordering_id
from sems s1
where s1.id = s.id
order by s1.ordering_id desc
limit 2
)
group by id
This assumes that (id, ordering_id) tuples are unique. If not, and there are ties in the top 2, all related records will be taken into account.
If your data is not too numerous, you can use:
SELECT id,
SUBSTRING_INDEX(GROUP_CONCAT(type ORDER BY ? DESC SEPARATOR '/'), '/', -2) as types
FROM `sems`
GROUP by year;.
The ? is for the column used to define "latest"

overall rank working with using FIND_IN_SET but department wise not working rank query

I have tried to get overall rank using FIND_IN_SET, it's working, at the same time using department_id 105 it's working.
query:SELECT id, emp_id ,emp_name, dept_id, total_pt, FIND_IN_SET( total_pt, ( SELECT GROUP_CONCAT( total_pt ORDER BY total_pt DESC )
FROM performance_score ) ) AS rank,overall_rank FROM performance_score_bk where dept_id = 105
But after i tried to get the rank with department_id 111, it'not starting with rank 1, it's starting 8 and no proper order.
Please check the inform me where i did a mistake.
query:SELECT id, emp_id ,emp_name, dept_id, total_pt, FIND_IN_SET( total_pt, ( SELECT GROUP_CONCAT( total_pt ORDER BY total_pt DESC )
FROM performance_score ) ) AS rank,overall_rank FROM performance_score_bk where dept_id = 111
Simulating rank on MySQL versions 5.7 and earlier is a real pain-in-the-neck. If you have a long term need for rank, or other analytic functions, then consider upgrading to MySQL 8+. In MySQL 8 we can easily write:
SELECT
dept_id,
total_pt,
RANK() OVER (PARTITION BY dept_id ORDER BY total_pt DESC) `rank`,
RANK() OVER (ORDER BY total_pnt DESC) overall_rank
FROM yourTable
ORDER BY
dept_id,
total_pt DESC;