SQL Multi Order by Count with Criteria - mysql

I want to query standings from MotoGP Race result
my sql is
SELECT `Rider`, `Team`, `Bike`,SUM(`Points`)
FROM `table_name`
WHERE `Year` = 2015 AND `Classes` = "MotoGP"
GROUP BY `Year`,`Rider`
HAVING SUM(`Points`)
ORDER BY SUM(`Points`) DESC
If 2 or more riders have same SUM('Points'), the next order is by number of 1st race position.
I put the race position on 'Pos' field.
Pos value: 1,2,3,4,5 ...
Please help for the 2nd order. Thank you

You just need to change the HAVING clause:
ORDER BY SUM(`Points`) DESC,
SUM(RacePosition = 1) DESC
For multiple positions, I think you need to add the condition for each one:
ORDER BY SUM(`Points`) DESC,
SUM(RacePosition = 1) DESC,
SUM(RacePosition = 2) DESC,
SUM(RacePosition = 3) DESC
At some point, perhaps SUM(RacePosition) would do what you want.

Related

Add second column to order by mysql in a group_concat

I have this query I made based on someone else question here.
SELECT *, FIND_IN_SET( score, ( SELECT GROUP_CONCAT( score ORDER BY score ASC) FROM EventPlayerResult WHERE eventId = 'EventTest0') ) AS position FROM EventPlayerResult WHERE eventId = 'EventTest0' ORDER BY position ASC LIMIT 10
It gives me a leaderboard for the top 10 players. But when I run it, if 2 players has the same score, I need it to filter by another column (energyLeft). So I tried to add , energyLeft DESC inside of my GROUP_CCONCAT but it doesnt change anything. im not familiar with group concat and find in set. So where should I add the logic to order by energyLeft after ordering by score.
I tried something like this :
SELECT *, FIND_IN_SET( score, ( SELECT GROUP_CONCAT( score ORDER BY score ASC, energyLeft DESC) FROM EventPlayerResult WHERE eventId = 'EventTest0') ) AS position FROM EventPlayerResult WHERE eventId = 'EventTest0' ORDER BY position ASC LIMIT 10
You should use the player and not the score inside GROUP_CONCAT() so that the players are ranked by score first and then by energyLeft.
Assuming there is a column like player_id in the table:
SELECT *,
FIND_IN_SET(
player_id,
(
SELECT GROUP_CONCAT(player_id ORDER BY score ASC, energyLeft DESC) FROM EventPlayerResult WHERE eventId = 'EventTest0'
)
) AS position
FROM EventPlayerResult
WHERE eventId = 'EventTest0'
ORDER BY position ASC LIMIT 10;

Mysql filter SELECT query result.

I have the following query.
SELECT COUNT(id) AS NumResults, race_date AS RaceDate, race_time AS RaceTime
FROM results
WHere jockeys_claim = 10
GROUP BY race_date DESC, race_time ASC
I would then like to filter out the NumResults , so the table only shows results where the NumResults = 1. Thanks for looking.
Use the HAVING clause to filter the results of an aggregate function (the COUNT in your case)
SELECT COUNT(id) AS NumResults, race_date AS RaceDate, race_time AS RaceTime
FROM results
WHere jockeys_claim = 10
GROUP BY race_date, race_time
HAVING COUNT(id) = 1
ORDER BY race_date DESC, race_time ASC

Mysql query with multiple ORDER BY clause and IF conditions

I am trying to query based on these conditions in an orders table,
// This is not an actual query
SELECT *
IF (store_id = 3) THEN ORDER BY WEIGHT DESC,
ELSEIF (STORE_ID = 7) THEN ORDER BY WEIGHT DESC
ELSEIF ORDER BY WEIGHT = DESC
ELSEIF (EQUAL WEIGHT) ORDER BY ORDER_DATE DESC
ELSEIF (EQUAL WEIGHT AND EQUAL ORDER_DATE) ORDER BY STORE_ID DESC
ELSEIF (EQUAL WEIGHT AND EQUAL ORDER_DATE AND EQUAL STORE_ID) ORDER BY
SHIPPING_METHOD DESC
FROM TABLE orders WHERE carrier_name = 'XXX'
This is as far as what I have got,
//Actual query
SELECT id,store_id,weight
FROM orders
WHERE carrier_name = 'XXX'
ORDER BY
IF(store_id = 3,weight,'')DESC,
IF(store_id = 3,order_date,'')DESC,
IF(store_id = 3,store_id,'')DESC,
IF(store_id = 3,shipping_method,'')DESC,
IF(store_id = 7,weight,'')DESC,
IF(store_id = 7,order_date,'')DESC,
IF(store_id = 7,store_id,'')DESC,
IF(store_id = 7,shipping_method,'')DESC,
IF(TRUE,weight,'')DESC,
IF(TRUE,order_date,'')DESC,
IF(TRUE,store_id,'')DESC,
IF(TRUE,shipping_method,'')DESC
The result obtained is
I am not sure why 53.39 and 30.35 are not sorted. What am I doing wrong?
Please suggest if there is a better way to attain this.
This is the required result,
Based on your expected output, the following query should give you what you want:
SELECT *
FROM orders
WHERE carrier_name = 'XXX'
ORDER BY CASE WHEN store_id = 3 THEN 0
WHEN store_id = 7 THEN 1
ELSE 2 END,
store_id,
weight DESC
For an explanation of the logic in the ORDER BY clause, the first condition puts store_id 3 first, followed by 7, followed by everything else. The next conditions orders each of these three groups in ascending order by the store_id. Note that for 3 and 7, this second step will be ignored, because the store_id value is the same for these groups (3 and 7 respectively). Finally, the third condition is to order by the weight in descending order.
ORDER BY
weight DESC, -- as i can see all true in your cases
order_date DESC,
store_id DESC,
shipping_method DESC

SQL select aggregate values in columns

I have a table in this structure:
editor_id
rev_user
rev_year
rev_month
rev_page
edit_count
here is the sqlFiddle: http://sqlfiddle.com/#!2/8cbb1/1
I need to surface the 5 most active editors during March 2011 for example - i.e. for each rev_user - sum all of the edit_count for each rev_month and rev_year to all of the rev_pages.
Any suggestions how to do it?
UPDATE -
updated fiddle with demo data
You should be able to do it like this:
Select the total using SUM and GROUP BY, filtering by rev_year and rev_month
Order by the SUM in descending order
Limit the results to the top five items
Here is how:
SELECT * FROM (
SELECT rev_user, SUM(edit_count) AS total_edits
FROM edit_count_user_date
rev_year='2006' AND rev_month='09'
GROUP BY rev_user
) x
ORDER BY total_edits DESC
LIMIT 5
Demo on sqlfiddle.
Surely this is as straightforward as :
SELECT rev_user, SUM(edit_count) as TotalEdits
FROM edit_count_user_date
WHERE rev_month = 'March' and rev_year = '2014'
GROUP BY rev_user
ORDER BY TotalEdits DESC
LIMIT 5;
SqlFiddle here
May I also suggest using a more appropriate DATE type for the year and month storage?
Edit, re new Info
The below will return all edits for the given month for the 'highest' MonthTotal editor, and then re-group the totals by the rev_page.
SELECT e.rev_user, e.rev_page, SUM(e.edit_count) as TotalEdits
FROM edit_count_user_date e
INNER JOIN
(
SELECT rev_user, rev_year, rev_month, SUM(edit_count) AS MonthTotal
FROM edit_count_user_date
WHERE rev_month = '09' and rev_year = '2010'
GROUP BY rev_user, rev_year, rev_month
ORDER BY MonthTotal DESC
LIMIT 1
) as x
ON e.rev_user = x.rev_user AND e.rev_month = x.rev_month AND e.rev_year = x.rev_year
GROUP BY e.rev_user, e.rev_page;
SqlFiddle here - I've adjusted the data to make it more interesting.
However, if you need to do this across several months at a time, it will be more difficult given MySql's lack of partition by / analytical windowing functions.

MySql sort within sorted results set

I have the following query which queries a table of sports results for the last 20 matches that involved a teams, returning goals conceeded in each of these matches.
SELECT *, `against` AS `goalsF` , `for` AS `goalsA`
FROM `matches` , `teams` , `outcomes`
WHERE (
`home_team_id`=7 AND `matches`.away_team_id = `teams`.team_id
OR
`away_team_id`=7 AND `matches`.home_team_id = `teams`.team_id
)
AND `matches`.score_id = `outcomes`.outcome_id
ORDER BY `against', `date` DESC
LIMIT 0 , 20
I want sort the results by goals conceeded and then within each group of goals conceeded by date so for example.
the first 4 results where goals conceded=1 in date order
then the next 3 might be results where conceded=2 in date order
I have tried ORDER by date,against - this gives me a strict date order
I have tried ORDER by against,date - this gives me matches beyond the last 20
Is it possible to do what I want to do?
Thanks everyone, I found this worked. This solution was posted by another user but then was removed, not sure why?
SELECT * FROM (
SELECT *, `against` AS `goalsF` , `for` AS `goalsA`
FROM `matches` , `teams` , `outcomes`
WHERE (
`home_team_id`=7 AND `matches`.away_team_id = `teams`.team_id
OR
`away_team_id`=7 AND `matches`.home_team_id = `teams`.team_id
)
AND `matches`.score_id = `outcomes`.outcome_id
ORDER by `goalsF`
LIMIT 0 , 20
) res
ORDER BY `date` DESC
If you want to limit by date, add the date range you are looking for into your WHERE clause and then order by the number of goals conceded.