GROUP BY id After ORDER BY time - mysql

This query returns all items where the difference between the timestamps is less than 180 seconds.
The problem is, after all this is done, I need to then limit the results to the one most recent entry per facebook_id.
I tried using GROUP BY facebook_id, but it doesn't work because if I GROUP BY facebook_id before ORDER BY 'time', it picks the older entry instead of the newer entry which is not what I want.
Is there any way to GROUP BY after ORDER BY?
SELECT facebook_id,
TIMESTAMPDIFF(SECOND, `time`, '$mytime') AS `timediff`
FROM `table`
WHERE `facebook_id` != $fbid
HAVING `timediff` <= '180'
ORDER BY `time` DESC
Thanks for your help!
Note: I did try the suggested solutions to this question but had no success. GROUP BY after ORDER BY

You can use a self join by calculating maximum value of time column and join with 2 conditions one with facebook_id and second to match the time from table to the max_time of second query which will return recent entry against each facebook_id
SELECT t.*,
TIMESTAMPDIFF(SECOND, `time`, '$mytime') AS `timediff`
FROM `table` t
JOIN (
SELECT facebook_id,MAX(`time`) max_time FROM `table` GROUP BY facebook_id
) t1
ON(t.facebook_id= t1.facebook_id AND t.`time` = t1.max_time)
WHERE t.`facebook_id` != $fbid
HAVING `timediff` <= '180'
ORDER BY t.`time` DESC

SELECT fid, timediff
FROM (
SELECT facebook_id as fid,
TIMESTAMPDIFF(SECOND, `time`, '$mytime') AS timediff
FROM `table`
WHERE `facebook_id` != $fbid
HAVING `timediff` <= '180'
ORDER BY `time` DESC
) entries
GROUP BY entries.fid
Please let me know if you have any questions!

Related

MySql last record from group by item_id with order by date

My database table name is ledgers and fields are id, item_id, date, ...other fields
I Want the last record from (groupBy item_id order by date ASC). from each group.
I tried below query
select
`id`,
`item_id`,
`date`,
`opening_quantity`,
`closing_quantity`,
`item_rate`,
`item_value`,
`previous_rate`
from `ledgers`
where date(`date`) >= ? and date(`date`) <= ?
group by `item_id`
order by `date` desc
Can you guys please help.
You can filter with a correlated subquery:
select t.*
from `ledgers` t
where
date(t.`date`) >= ?
and date(t.`date`) <= ?
and t.`date` = (
select max(t1.`date`)
from `ledgers` t1
where t1.`item_id` = t.`item_id`
)
For performance, consider an index on (item_id, date).
Another option is to use rank() (available in MySQ 8.0 only):
select *
from (
select
t.*,
rank() over(partition by `item_id` order by `date` desc) rn
from `ledgers` t
where date(t.`date`) >= ? and date(t.`date`) <= ?
) t
where rn = 1

MySQL Nested Select Query?

Ok, so I have the following query:
SELECT MIN(`date`), `player_name`
FROM `player_playtime`
GROUP BY `player_name`
I then need to use this result inside the following query:
SELECT DATE(`date`) , COUNT(DISTINCT `player_name`)
FROM `player_playtime /*Use previous query result here*/`
GROUP BY DATE( `date`) DESC LIMIT 60
How would I go about doing this?
You just need to write the first query as a subquery (derived table), inside parentheses, pick an alias for it (t below) and alias the columns as well.
The DISTINCT can also be safely removed as the internal GROUP BY makes it redundant:
SELECT DATE(`date`) AS `date` , COUNT(`player_name`) AS `player_count`
FROM (
SELECT MIN(`date`) AS `date`, `player_name`
FROM `player_playtime`
GROUP BY `player_name`
) AS t
GROUP BY DATE( `date`) DESC LIMIT 60 ;
Since the COUNT is now obvious that is only counting rows of the derived table, you can replace it with COUNT(*) and further simplify the query:
SELECT t.date , COUNT(*) AS player_count
FROM (
SELECT DATE(MIN(`date`)) AS date
FROM player_playtime
GROUP BY player_name
) AS t
GROUP BY t.date DESC LIMIT 60 ;

Execute query that normally runs on a single ID for every ID

So I have this query:
SELECT ABS(
TIMESTAMPDIFF(MINUTE, NOW(),
(SELECT MAX(`Time`) FROM ddHistorical WHERE ID = '5')
)
)
I want to run that on every ID in my database, how would I do that?
This works (http://www.sqlfiddle.com/#!2/e8ac0/3/0)
SELECT Abs(Timestampdiff(minute, Now(), (SELECT Max( ` time ` )
FROM ddhistorical
WHERE id = a.id
GROUP BY id)))
FROM ddhistorical AS A
GROUP BY id
Try this:-
SELECT ABS(TIMESTAMPDIFF(MINUTE, NOW(), (SELECT MAX(`Time`) FROM ddHistorical

Whats wrong with query? wrong syntax error? Group by no working

I have written a query
(SELECT TimeStamp, AVG(FwdHr), W
FROM Meter_Data
WHERE (TimeStamp Between 1370476500 AND 1370477100 AND DeviceID = '1'
GROUP BY MeterID ORDER BY TimeStamp)
UNION
(SELECT TimeStamp, AVG(FwdHr), W
FROM Meter_Data
WHERE TimeStamp Between 1370496006 AND 1370496606 AND DeviceID = '1'
GROUP BY MeterID ORDER BY TimeStamp)
i want to select avg(FwdHr) from table for every meter id between two time stamps
and then union it with same query having different time intervals
The parenthesis in the query are unbalance and unnecessary.
ORDER BY and GROUP BYcan only be applied to the final result set, not for intermediate results.
Also the parenthesis are unnecessary
SELECT * FROM
(
SELECT TimeStamp, AVG(FwdHr), W
FROM Meter_Data
WHERE TimeStamp Between 1370476500 AND 1370477100
AND DeviceID = '1'
UNION
SELECT TimeStamp, AVG(FwdHr), W
FROM Meter_Data WHERE TimeStamp Between 1370496006 AND 1370496606
AND DeviceID = '1'
) as myTable
GROUP BY myTable.MeterID
ORDER BY myTable.TimeStamp
Or even better: Use OR instead of UNION
SELECT TimeStamp, AVG(FwdHr), W
FROM Meter_Data
WHERE DeviceID = '1'
AND (TimeStamp Between 1370496006 AND 1370496606
OR
TimeStamp Between 1370476500 AND 1370477100 )
GROUP BY MeterID
ORDER BY TimeStamp

MYSQL Query : How to get values per category?

I have huge table with millions of records that store stock values by timestamp. Structure is as below:
Stock, timestamp, value
goog,1112345,200.4
goog,112346,220.4
Apple,112343,505
Apple,112346,550
I would like to query this table by timestamp. If the timestamp matches,all corresponding stock records should be returned, if there is no record for a stock for that timestamp, the immediate previous one should be returned. In the above ex, if I query by timestamp=1112345 then the query should return 2 records:
goog,1112345,200.4
Apple,112343,505 (immediate previous record)
I have tried several different ways to write this query but no success & Im sure I'm missing something. Can someone help please.
SELECT `Stock`, `timestamp`, `value`
FROM `myTable`
WHERE `timestamp` = 1112345
UNION ALL
SELECT `Stock`, `timestamp`, `value`
FROM `myTable`
WHERE `timestamp` < 1112345
ORDER BY `timestamp` DESC
LIMIT 1
select Stock, timestamp, value from thisTbl where timestamp = ? and fill in timestamp to whatever it should be? Your demo query is available on this fiddle
I don't think there is an easy way to do this query. Here is one approach:
select tprev.*
from (select t.stock,
(select timestamp from t.stock = s.stock and timestamp <= <whatever> order by timestamp limit 1
) as prevtimestamp
from (select distinct stock
from t
) s
) s join
t tprev
on s.prevtimestamp = tprev.prevtimestamp and s.stock = t.stock
This is getting the previous or equal timestamp for the record and then joining it back in. If you have indexes on (stock, timestamp) then this may be rather fast.
Another phrasing of it uses group by:
select tprev.*
from (select t.stock,
max(timestamp) as prevtimestamp
from t
where timestamp <= YOURTIMESTAMP
group by t.stock
) s join
t tprev
on s.prevtimestamp = tprev.prevtimestamp and s.stock = t.stock