I want to delete rows with an offset, so I am forced to use a nested query since its not support in the raw DELETE clause.
I know this would worked (ID is the primary key):
DELETE FROM customers
WHERE ID IN (
SELECT ID
FROM customers
WHERE register_date > '2012-01-01'
ORDER BY register_date ASC
LIMIT 5, 10
);
However, this is unsupported in my version as I get the error
This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'.
Server version: 10.4.22-MariaDB
What can I do to achieve the same result as above that is supported in my version.
CREATE TABLE customers (
ID INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL,
REGISTER_DATE DATETIME NOT NULL
);
Join the table to a subquery that uses ROW_NUMBER() window function to sort the rows and filter the rows that you want to be deleted:
DELETE c
FROM customers c
INNER JOIN (
SELECT *, ROW_NUMBER() OVER (ORDER BY register_date) rn
FROM customers
WHERE register_date > '2012-01-01'
) t ON t.ID = c.ID
WHERE t.rn > 5 AND t.rn <= 15; -- get 10 rows with row numbers 6 - 15
See the demo.
If I did not miss something a simple delete with join will do the job...
delete customers
from (select *
from customers
WHERE register_date > '2012-01-01'
order by register_date asc
limit 5, 2) customers2
join customers on customers.id = customers2.id
Here is a demo for your version of MariaDB
You could try assigning a rank to your rows with the ROW_NUMBER window function, then catch those rows whose rank position is between 5 and 15.
DELETE FROM customers
WHERE ID IN (
SELECT *
FROM (SELECT ID,
ROW_NUMBER() OVER(
ORDER BY IF(register_date>'2012-01-01', 0, 1)
register_date ) AS rn
FROM customers) ranked_ids
WHERE rn > 4
AND rn < 16
);
This would safely avoid the use of LIMIT, though achieves the same result.
EDIT. Doing it with a join.
DELETE FROM customers c
INNER JOIN (SELECT ID,
ROW_NUMBER() OVER(
ORDER BY IF(register_date>'2012-01-01', 0, 1)
register_date ) AS rn
FROM customers) ranked_ids
WHERE
) ids_to_delete
ON c.ID = ids_to_delete.ID
AND ids_to_delete.rn > 4
AND ids_to_delete.rn < 16
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).
I have a table like the one above, I want to calculate total of amount with largest log_id and group by user_id.
the results will be as below :
this is my example code but this is not work :(
CREATE TABLE IF NOT EXISTS example (
`id` INT,
`log_id` INT,
`user_id` INT,
`amount` INT
);
INSERT INTO example VALUES
(1,1,10,4),
(2,2,10,8),
(3,3,10,2),
(4,3,10,6),
(5,1,12,9),
(6,2,12,4),
(7,1,13,7),
(8,1,14,2),
(9,2,14,6),
(10,1,15,7),
(11,2,15,4),
(12,3,15,9),
(13,3,15,6);
select max(log_id) as log_id, user_id, amount from example group by user_id, amount
Any ideas?
Thanks, xmush
You can go for RANK function and get data.
Schema (MySQL v8.0)
CREATE TABLE test
(
id INT,
logid int,
userid int,
amount INT
);
insert into test(id, logid, userid, amount)
values (1, 1, 12,9),
(2,2,12,4);
Query #1
WITH testcte AS (
SELECT *, RANK() OVER (PARTITION BY userid order by logid desc) as rnk from test
)
SELECT * FROM testcte WHERE rnk = 1;
id
logid
userid
amount
rnk
2
2
12
4
1
View on DB Fiddle
Here's a 'traditional' (pre-8.0) approach...
Grab the rows holding the largest log_id for each user...
SELECT x.*
FROM example x
JOIN
( SELECT user_id
, MAX(log_id) log_id
FROM example
GROUP
BY user_id
) y
ON y.user_id = x.user_id
AND y.log_id = x.log_id
Aggregate the resulting data set...
SELECT x.log_id
, x.user_id
, SUM(amount) total
FROM example x
JOIN
( SELECT user_id, MAX(log_id) log_id FROM example GROUP BY user_id ) y
ON y.user_id = x.user_id
AND y.log_id = x.log_id
GROUP
BY x.log_id
, x.user_id
ORDER
BY user_id;
I'm having trouble retrieving the rankings from a single line that has some uuid from that:
SELECT uuid , AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average
from elo_ranked group by uuid
order by AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 desc
limit 3
I specify that the above function works and has the expected result.
Is this what you want?
SELECT uuid, AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average ,
RANK() OVER (ORDER BY AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 DESC) as ranking
FROM elo_ranked
GROUP BY uuid
ORDER BY AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 desc
LIMIT 3;
EDIT:
To rank a specific user, use a subquery:
SELECT u.*
FROM (SELECT uuid, AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average ,
RANK() OVER (ORDER BY AVG(nodebuff+debuff+archer+builduhc+uhc+gapple)/6 DESC) as ranking
FROM elo_ranked
GROUP BY uuid
) u
WHERE uuid = ?;
Also, I'm not sure if you need the aggregation. That would only be needed if a user had multiple rows in the elo_ranked table. If not needed, then you should use:
SELECT u.*
FROM (SELECT uuid, (nodebuff+debuff+archer+builduhc+uhc+gapple)/6 as Average ,
RANK() OVER (ORDER BY (nodebuff+debuff+archer+builduhc+uhc+gapple)/6 DESC) as ranking
FROM elo_ranked
) u
WHERE uuid = ?;
The GROUP BY has a lot of overhead, so this should be faster (unless MySQL has sophisticated optimizations to avoid the aggregation when grouping by a primary key).
I have a table with
orderNumber(pk) , customerNumber , comment
I have to count the maximum order placed by a user and show its user ID and MAX count . I have following Query
It shows the count Right but it takes the first CustomerNumber in the table
SELECT maxCount.customerNumber , MAX(`counted`) FROM
(
SELECT customerNumber, COUNT(*) AS `counted`
FROM `orders`
GROUP BY `customerNumber`
)as maxCount
Thanks & regards
Just use ORDER BY with your inner query:
SELECT customerNumber, COUNT(*) AS `counted`
FROM `orders`
GROUP BY `customerNumber`
ORDER BY COUNT(*) DESC
LIMIT 1
If you want to return all customer numbers in the event of a tie, you can use a HAVING clause with a subquery which identifies the maximum count:
SELECT customerNumber, COUNT(*) AS counted
FROM orders
GROUP BY customerNumber
HAVING COUNT(*) = (SELECT MAX(t.counted) FROM (SELECT COUNT(*) AS counted
FROM orders
GROUP BY customerNumber) t)
Demo here:
SQLFiddle