Get last rows based on datetime and using name - mysql

I have the following table in MYSQL:
DATETIME dt
VARCHAR location
FLOAT temperature
This table contains many temperatures measured at different locations. Now I need a SQL query to get the last measurements done for each location.
I actually have no idea how to do that.

Note that while doing group by aggregate its better to have the column selected prior doing group by.
select
t1.location,
t2.t2_dt as dt,
t1.temperature
from table_name t1
join
(
select
location,
temperature,
max(dt) as t2_dt
from table_name
group by location
)t2
on t2.location = t1.location AND t1.dt = t2.t2_dt
group by t1.location
DEMO

This will do your job
select * from
(select location, temperature, dt from my_table) as tab
join
(select max(dt) as max_dt from my_table
group by location) as max_date_tab
on (tab.dt = max_date_tab.max_dt)

Related

How to perform calculations on queries in mysql that return multiple values

First query:
SELECT COUNT(sales.ucid) AS totalOutcomes
FROM sales
group by date(sales.saleDate)
Second query:
SELECT COUNT(*) AS joinedOutcomes
FROM sales
JOIN calls
ON sales.ucid = calls.call_id
group by date(sales.saleDate)
I now want to use the output from the second query and divide that by the output from the first query.
Can someone please help with this? Thanks!
Join the two queries.
SELECT t1.date, joinedOutcomes/totalOutcomes
FROM (
SELECT date(sales.saleDate) AS date, COUNT(sales.ucid) AS totalOutcomes
FROM sales
GROUP BY date
) AS t1
JOIN (
SELECT date(sales.saleDate) AS date, COUNT(*) AS joinedOutcomes
FROM sales
JOIN calls ON sales.ucid = calls.call_id
group by date
) AS t2 ON t1.date = t2.date

Select values with latest date and group by an other column

See My Table and query here (on sqlfiddle) Myquery is fetching exact results that I need but it takes long time when data is more than 1000 rows. I need to make it Efficient
Select `id`, `uid`, case when left_leg > right_leg then left_leg
else right_leg end as Max_leg,`date` from
(
SELECT * FROM network t2 where id in (select id from
(select id,uid,`date` from (SELECT * FROM network order by uid,
`date` desc) t4 group by uid) t3) and
(left_leg>=500 or right_leg>=500))t1
Want to pick data from network againt latest dates for each uid
Wanted to pick data where left_leg >=500 or right_leg >=500
Wanted to pick only bigger of two legs (left or right)
Whole query might have some problems but Core issue is with this code
SELECT * FROM network t2 where id in (select id from
(select id,uid,`date` from (SELECT * FROM network order by uid,
`date` desc) t4 group by uid) t3)
I want to improve this query because it fetches esults so much slow when data grows.
Taking your description:
first find the max date for each uid
then find the associate ids
filter on the leg values
Example:
SELECT id, uid, GREATEST(left_leg, right_leg) as max_leg
FROM network
WHERE (uid, `date`) IN (SELECT uid, MAX(`date`)
FROM network
GROUP BY uid)
AND (left_leg > 500 or right_leg > 500)
Note that this means that if the latest date for a uid does not have some legs > 500, then the records won't show up in the result. If you want the latest records with legs > 500, the leg filter has to be moved in.
Add an index on (uid,date):
ALTER TABLE network ADD INDEX uid_date( uid, date )
and try something like:
SELECT n.id, n.uid, greatest( n.right_leg, n.left_leg ) as max_leg, n.date
FROM
( SELECT uid,max(date) as latest FROM network
WHERE right_leg>=500 OR left_leg >=500
GROUP BY uid
) ng
JOIN network n ON n.uid = ng.uid AND n.date = ng.latest

MySQL - Fetching lowest value

My database structure contains columns: id, name, value, dealer. I want to retrieve row with lowest value for each dealer. I've been trying to mess up with MIN() and GROUP BY, still - no solution.
Solution1:
SELECT t1.* FROM your_table t1
JOIN (
SELECT MIN(value) AS min_value, dealer
FROM your_table
GROUP BY dealer
) AS t2 ON t1.dealer = t2.dealer AND t1.value = t2.min_value
Solution2 (recommended, much faster than solution1):
SELECT t1.* FROM your_table t1
LEFT JOIN your_table t2
ON t1.dealer = t2.dealer AND t1.value > t2.value
WHERE t2.value IS NULL
This problem is very famous, so there is a special page for this in Mysql's manual.
Check this: Rows Holding the Group-wise Maximum/Minimum of a Certain Column
select id,name,MIN(value) as pkvalue,dealer from TABLENAME
group by id,name,dealer;
here you group all rows by id,name,dealer and then you will get min value as pkvalue.
SELECT MIN(value),dealer FROM table_name GROUP BY dealer;
First you need to resolve the lowest value for each dealer, and then retrieve rows having that value for a particular dealer. I would do this that way:
SELECT a.*
FROM your_table AS a
JOIN (SELECT dealer,
Min(value) AS m
FROM your_table
GROUP BY dealer) AS b
ON ( a.dealer= b.dealer
AND a.value = b.m )
Try following:
SELECT dealer, MIN(value) as "Lowest value"
FROM value
GROUP BY dealer;
select id, name, value, dealer from yourtable where dealer
in(select min(dealer) from yourtable group by name, value)
These answers seem to miss the edge case of having multiple minimum values for a dealer and only wanting to return one row.
If you want to only want one value for each dealer you can use row_number partition - group - the table by dealer then order the data by value and id. we have to make the assumption that you will want the row with the smallest id.
SELECT ord_tbl.id,
ord_tbl.name,
ord_tbl.value,
ord_tbl.dealer
FROM (SELECT your_table.*,
ROW_NUMBER() over (PARTITION BY dealer ORDER BY value ASC, ID ASC)
FROM your_table
) AS ord_tbl
WHERE ord_tbl.ROW_NUMBER = 1;
Be careful though that value, id and dealer are indexed. If not this will do a full table scan and can get pretty slow...

How to use distinct and limit together

I have a mysql query. I need to get last value from columns Lat,Lng from my table but serial_number column needs to be distinct.
How to make such a query?
This is needed as I am using this coordinates to load it to Google map. So when the Google maps loads I need to have a marker on each last coordinates where vehicle is.
SELECT m.*
FROM (
SELECT DISTINCT serial_number
FROM mytable
) md
JOIN mytable m
ON m.id =
(
SELECT id
FROM mytable mi
WHERE mi.serial_number = md.serial_number
ORDER BY
mi.time DESC, mi.id DESC
LIMIT 1
)
Create an index on (serial_number, time, id) for this to work fast.
If you want to retrieve the last record for a certain serial_number, just use this:
SELECT *
FROM mytable
WHERE serial_number = :my_serial_number
ORDER BY
time DESC, id DESC
LIMIT 1
1#
Assuming that max ID will always give you last lat and lon, the query becomes quite simple -
SELECT t2.*
FROM table t2
where t2.id IN
(
SELECT max(t1.id)
FROM table t1
GROUP BY t1.serial_number
)
2#
If you need to consider time also, then you will need to do it this way. Here, in the inner query, max_time of each serial_number is obtained. Then this max_time and serial_number is joined with the outer table time and serial_number respectively, to get distinct records with last lat and lon.
SELECT *
FROM table t2,
(
SELECT max(t1.time) max_time, t1.serial_number
FROM table t1
GROUP BY t1.serial_number
) new_table
WHERE t2.time=new_table.max_time
AND t2.serial_number=new_table.serial_number
Try this
select distinct serial_number, *
from table t
inner join table t1 on t1.serial_number = t.serial_number and t1.id = (select max id from table t2 where t2.serial_number = t1.serial_number)

Diff value last two record by datetime

I have table with id, item_id, value (int), run (datetime) and i need select value diff betwen last two run per *item_id*.
SELECT item_id, ABS(value1 - value2) AS diff
FROM ( SELECT h.item_id, h.value AS value1, h2.value AS value2
FROM ( SELECT id, item_id, value
FROM table_name
GROUP BY item_id
ORDER BY run DESC) AS h
INNER JOIN ( SELECT id, item_id, value
FROM table_name
ORDER BY run DESC) AS h2
ON h.item_id = h2.item_id AND h.id != h2.id
GROUP BY item_id) AS h3
I believe this should do the trick for you. Just replace table_name to correct name.
Explanation:
Basicly I join the table with itself in a run DESC order, JOIN them based on item_id but also on id. Then I GROUP BY them again to remove potential 3rd and so on cases. Lastly I calculate the difference between them through ABS(value1 - value2).
SELECT t2.id, t2.item_id, (t2.value- t1.value) valueDiff, t2.run
FROM ( table_name AS t1
INNER JOIN
table_name AS t2
ON t1.run = (SELECT MAX(run) FROM table_name where run < t2.run)
and t1.item_id = t2.item_id)
This is assuming you want the diff between a record and the record with the previous run