MySQL: How to limit results to max value of another field? - mysql

In this scenario, I am trying to report on the operating_system_version for each distinct computer_id where the report_id for that computer_id is the greatest.
Currently, I am getting the below results:
operating_system_version | computer_id | report_id
10.8 | 1 | 10
10.9 | 1 | 20
10.9 | 2 | 11
10.8 | 2 | 21
The above is returned by this statement:
SELECT operating_systems.operating_system_version,
reports.computer_id,
reports.report_id
FROM operating_systems
INNER JOIN reports
ON operating_systems.report_id = reports.computer_id
Instead, would like return the most recent (highest report_id) operating_system_version for each distinct computer_id, for example:
operating_system_version | computer_id | report_id
10.9 | 1 | 20
10.8 | 2 | 21
I am brand new to SQL .. Appreciate any help.

You would need to add a group by statement and a having statement.
The group by would look like
group by computer_id
The having would look like
having report_id= (select max(report_id) )

SELECT operating_systems.operating_system_version,
reports.computer_id,
reports.report_id
FROM operating_systems INNER JOIN reports ON operating_systems.report_id = reports.computer_id
WHERE NOT EXISTS (SELECT 1
FROM reports r2
WHERE r2.computer_id = reports.computer_id
AND r2.reports_id > reports.reports_id)

A subquery would lead you to desired end result:
SELECT os.operating_system_version,
r2.computer_id,
MAX(r2.report_id)
FROM (
SELECT DISTINCT computer_id
FROM reports
) r
INNER JOIN operating_systems os
ON os.report_id = r.computer_id
INNER JOIN reports r2
ON r2.computer_id = r.computer_id

Need to do a better job looking through other posts. This question is answered in an excellent post at: SQL Select only rows with Max Value on a Column

Related

Viewing totals (Format below)

With the code shown below:
SELECT c.idBase, t.Estado FROM argentina.Tickets_2018 t
LEFT JOIN argentina.ContenidoBases c
ON t.ANI = c.ANI
WHERE t.idCampania = 8 AND t.Fecha BETWEEN "2018-04-04" AND "2018-04-15"
The columns and data retrieved is like this:
Base | Estado
----------------
139 | ANSWER
139 | ANSWER
139 | NOANSWER
139 | NOANSWER
139 | ANSWER
What I want is to view info like this (totals):
Base | Estado | Total
----------------
139 | ANSWER | 3
139 | NOANSWER | 2
What I'm doing wrong in my code? (I have a lot of "Base"s (like 139, 45, 2, etc))
SELECT c.idBase, t.Estado, count(*) as total FROM argentina.Tickets_2018 t
LEFT JOIN argentina.ContenidoBases c
ON t.ANI = c.ANI
WHERE t.idCampania = 8 AND t.Fecha BETWEEN "2018-04-04" AND "2018-04-15"
Group by c.idBase, t.Estado
The group by will allow you to do a count which will give you the total :)
Using COUNT() and GROUP BY, this result is possible:
SELECT c.idBase, t.Estado, COUNT(c.idBase) AS `Total`
FROM argentina.Tickets_2018 t
LEFT JOIN argentina.ContenidoBases c ON t.ANI = c.ANI
WHERE t.idCampania = 8 AND t.Fecha BETWEEN "2018-04-04" AND "2018-04-15"
GROUP BY c.idBase, t.Estado
As seeing in your expected output, Base is the alias name for the id column. If so use SELECT id AS Base, and GROUP BY c.id. If not, your actual column name is idBase use the query above.

mysql sort by column with addotinal parameter

I'm not sou sure if this is possible at all but is worth asking the question.
I would like to sort table by drivers id's
SELECT * FROM test ORDER BY driverid DESC
there is another table 'drivers' with the list of drivers where each driver has corresponding que number:
driver | driverid | queno
-------------------
drv1 | 15 | 3
drv2 | 30 | 1
drv3 | 40 | 2
so from 'test' db I can take driverid. But I would like to sort out this listing not by driverid but by queno. Is there any way to bring queno to the game...
SELECT t.*
FROM test t
LEFT JOIN drivers d ON t.driverid = d.driverid
ORDER BY d.queno DESC
SELECT * FROM test JOIN drivers ON test.driverid=drivers.driverid ORDER BY queno DESC

Is it possible to make this query working properly?

I'm creating a simple game and I want to get the best lap_time for each type in the db.
However, my query returns the wrong player_id (3 in second row) and total_ranks (all ranks instead of count by type).
Link to sqlfiddle: http://sqlfiddle.com/#!9/a0c36a/2
Desired result
+--------+-----+-------+------------+----------------+-------------+
| level | cp | type | player_id | MIN(lap_time) | total_ranks |
+--------+-----+-------+------------+----------------+-------------+
| 1 | 1 | 0 | 1 | 10.5 | 4 |
| 1 | 1 | 1 | 2 | 10.45 | 3 |
+--------+-----+-------+------------+----------------+-------------+
Is it possible to make it work in 1 query or do I need at least 2?
Fiddle
Same concept as Tim, but with Total_Ranks column
SELECT level, cp, R.type, player_id, MinTime, Total_Ranks
FROM runtimes R
JOIN (SELECT TYPE, MIN(LAP_TIME) MinTime, Count(*) Total_Ranks
FROM RUNTIMES
GROUP BY TYPE) T on R.Type = T.Type
and R.lap_time = T.MinTime
WHERE level=1
AND cp=1
One canonical way to solve this problem in MySQL is to use a subquery to identify the minimum lap time for each type. Then join your full table to this to obtain the entire record. Note that a nice side effect of this approach is that we also get back ties if a given type have more than one person sharing the minimum lap time.
SELECT r1.*, r2.total_ranks
FROM runtimes r1
INNER JOIN
(
SELECT type, MIN(lap_time) AS min_lap_time, COUNT(*) AS total_ranks
FROM runtimes
GROUP BY type
) r2
ON r1.type = r2.type AND
r1.lap_time = r2.min_lap_time
Here is a link to your updated Fiddle:
SQLFiddle

Find duplicates from same table and constraint them from another table in sql

Oh, my title is not the best one and as English is not my main language maybe someone can fix that instead of downvoting if they've understood the issue here.
Basically i have two tables - tourneyplayers and results. Tourneyplayers is like a side table which gathers together tournament information across multiple tables - results, tournaments, players etc. I want to check duplicates from the results table over column day1_best, from single tournament and return all the tourneyplayers who have duplicates.
Tourneyplayers contain rows:
Tourneyplayers
tp_id | resultid | tourneyid
1 | 2 | 91
2 | 21 | 91
3 | 29 | 91
4 | 1 | 91
5 | 3 | 92
Results contains rows:
Results:
r_id | day1_best
1 | 3
2 | 1
3 | 4
.. | ..
21 | 1
.. | ..
29 | 2
Now tourney with id = 91 has in total 4 results, with id's 1,2,21 and 29. I want to return values which have duplicates, so currently the result would be
Result
tp_id | resultid | day1_best
1 | 2 | 1
2 | 21 | 1
I tried writing something like this:
SELECT *
FROM tourneyplayers
WHERE resultid
IN (
SELECT r1.r_id
FROM results AS r1
INNER JOIN results AS r2 ON ( r1.day1_best = r2.day1_best )
AND (
r1.r_id <> r2.r_id
)
)
AND tourneyid =91
But in addition to values which had the same day1_best it chose two more which did not have the same. How could i improve my SQL or rewrite it?
First you JOIN both tables, so you know how the data looks like.
SELECT *
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`;
Then using the same query you GROUP to see what tourneyid, day1_best combination has multiple rows
SELECT `tourneyid`, `day1_best`, count(*) as total
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`
GROUP BY `tourneyid`, `day1_best`;
Finally you use the base JOIN and perform a LEFT JOIN to see what rows has a match and show only those rows.
SELECT t.`tp_id`, r.`r_id`, r.`day1_best`
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`
LEFT JOIN (SELECT `tourneyid`, `day1_best`, count(*) as total
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`
GROUP BY `tourneyid`, `day1_best`
HAVING count(*) > 1) as filter
ON t.`tourneyid` = filter.`tourneyid`
AND r.`day1_best` = filter.`day1_best`
WHERE filter.`tourneyid` IS NOT NULL;
SQL DEMO
OUTPUT
Please try this :
Select tp.tp_id , tp.resultid ,r.day1_best from (Select * from Tourneyplayers
where tourneyid = 91)as tp inner join (select * from Result day1_best in(select
day1_best from result group by day1_best having count(*)>1 ) )as r on tp.resultid
= r.r_id ;

How to get only row without a specific value in a column

this is a huge problem i've to solve in sql but i don't know how.
This is my dataset:
customer; publisher; qty
This is a data sample:
CustA; PublX; 10
CustA; PublZ; 20
CustA; PublF; 30
CustB; PublX; 8
CustC; PublD; 9
CustD; PublX; 9
CustD; MyPub; 18
CustE; PublZ; 3
CustE; MyPub; 8
I need to do a Query that get ONLY Customer without "MyPubl" as publisher.
Obviously i can't do :
SELECT * from myTable where Publisher <>"MyPubl"
One solution can be that i create a subset table that aggregate customer in one row like this:
CustA; PublX PublZ PublF; 60
CustB; PublX; 8
etc...
Then with a INSTR i check if MyPub exists in second field ...
This solution my work.. so i ask you How can i do this in SQL (aggregate 'same' customers in one row) ?
Any others suggestion (maybe more elegant) ?
Thanks
You can use NOT IN with a sub query:
SELECT
customer,
publisher,
qty
FROM
books
WHERE
customer NOT IN (
SELECT
DISTINCT customer
FROM
books
WHERE
publisher = 'MyPub'
)
SQL Fiddle Demo
Which will output:
CUSTOMER | PUBLISHER | QTY
---------+-----------+-----
CustA | PublZ | 20
CustA | PublF | 30
CustB | PublX | 8
CustC | PublD | 9
Maybe this:
SELECT * FROM myTable
WHERE customer NOT IN (SELECT customer FROM myTable WHERE Publisher = "MyPubl")
Or if you just want the customers
SELECT DISTINCT customer FROM myTable
Or old skool...
SELECT DISTINCT x.customer
FROM my_table x
LEFT
JOIN my_table y
ON y.customer = x.customer
AND y.publisher = 'MyPub'
WHERE y.customer IS NULL;