Reputation: 29
I have a table pesajes where the weigh-ins of the competitors are stored
pesajes:
id championship competitor accepted time
1 18 1280 0 1370931202
2 18 1280 1 1370931784
3 18 1203 0 1370932502
4 18 870 1 1370934905
5 18 1203 0 1370961212
6 18 1100 0 1370984288
I want to select only the rows where the last weigh-in was 0 (accepted is 0), for example: In this case I want to return only the rows 5 and 6
I was using this query:
SELECT * FROM pesajes WHERE championship=18 and accepted=0 GROUP by id
Obviously this query does not work because, among other problems, it returns the row 1 and I do not want that row because the last weigh-in of the competitor 1280 is accepted. How could I solve it?
Upvotes: 1
Views: 116
Reputation: 16958
Your question falls into the category of retrieving the greatest-n-per-group rows. Beginning with MySQL 8 or MariaDB 10.2, you can use a partitioning non-aggregating Window Function:
WITH tmp AS (
SELECT p.*, ROW_NUMBER() OVER (
PARTITION BY competitor ORDER BY accepted DESC, id DESC) AS rn
FROM pesajes AS p
)
SELECT * FROM tmp WHERE accepted = 0 AND rn = 1;
or
SELECT * FROM (
SELECT p.*, ROW_NUMBER() OVER (
PARTITION BY competitor ORDER BY accepted DESC, id DESC) AS rn
FROM pesajes AS p
) as tmp
WHERE accepted = 0 AND rn = 1;
These queries create a partition for each competitor, ordered by accepted
, then id
. Finally, only the first (order by id
with rn=1
) rows are returned which "still" have accepted=0
.
If you want those last (ordered by id
) rows where accepted=0
, and it doesn't matter that one of the competitors already had an accepted=1
row, just remove the ORDER BY accepted
:
SELECT * FROM (
SELECT p.*, ROW_NUMBER() OVER (
PARTITION BY competitor ORDER BY id DESC) AS rn
FROM pesajes AS p
) as tmp
WHERE accepted = 0 AND rn = 1;
This would create a partition table, partitioned by competitor
, ordered by id
and selects each partition's first row (WHERE rn=1
) where that row has accepted=0
.
Upvotes: 1
Reputation: 2746
Query -
select * from champ c1 inner join
(select competitor, max(time_1) mtime from champ
group by competitor) c2
where c1.competitor = c2.competitor
and c1.time_1 >= c2.mtime
and c1.accepted = 0
Fiddle here
Upvotes: 0
Reputation: 999
Pretty much, you need:
accepted = 0
accepted = 1
Other answers use time
, so I provide an alternative without using that column. I decided to do this since you don't mention it at all, so I don't know how reliable it could be for what you need.
SELECT p.*
FROM pesajes p
JOIN (
SELECT MAX(id) AS id, SUM(accepted) AS criteria
FROM pesajes
GROUP BY championship, competitor
) filter ON filter.id = p.id AND filter.criteria = 0;
This will work in MySQL 5.5 up to 8.0.
And here is the fiddle.
Upvotes: 1