I have on table, that I record Car#,Date,RunHours as bellow:
Car# Date RunHours
125 2014-01-01 1250
125 2014-02-10 3250
215 2014-02-11 1400
215 2014-03-01 1800
125 2014-03-15 4100
215 2014-04-10 2500
I need the select result as bellow:
Car# Date Runhours Previous_Date Previous_RunHours
125 2014-01-01 1250 N/A N/A
125 2014-02-10 3250 2014-01-01 1250
215 2014-02-11 1400 N/A N/A
215 2014-03-01 1800 2014-02-11 1400
125 2014-03-15 4100 2014-02-10 3250
215 2014-04-10 2500 2014-02-11 1800
How can I do it.
Here is one method, using correlated subqueries to get the previous information:
select t.*,
(select t2.date
from table t2
where t2.car = t.car and t2.date < t.date
order by t2.date desc
limit 1
) as prev_date,
(select t2.runhours
from table t2
where t2.car = t.car and t2.date < t.date
order by t2.date desc
limit 1
) as prev_runhours
from table t;
For performance, you want an index on table(car, date).
Related
I have below mentioned tables: MySQL Version - 5.7.25
Table1:
ID ref
T-1 abc-1-x
T-2 abc-2-x
T-3 abc-3-x
T-4 abc-4-x
T-5 abc-5-x
Table2
ref_id value date
abc-1-x 250 2019-12-10 14:16:19
abc-2-x 500 2019-12-11 17:21:05
abc-3-x 100 2019-12-12 18:11:01
abc-4-x 150 2019-12-13 05:04:11
abc-5-x 120 2019-12-14 12:10:09
Table3
ID seq date2
T-1 1 2019-12-10 14:05:04
T-1 2 2019-12-10 21:17:01
T-1 3 2019-12-11 13:12:12
T-2 1 2019-12-11 14:13:46
T-2 2 2019-12-12 14:05:04
T-3 1 2019-12-12 14:05:04
T-3 2 2019-12-12 17:15:14
T-3 3 2019-12-13 10:09:08
T-3 4 2019-12-14 12:18:14
T-4 1 2019-12-13 01:01:04
T-4 2 2019-12-13 03:03:01
T-5 1 2019-12-15 14:05:04
By utilizing the above mentioned three tables, I want to compare the date of Table2 with Table3 against each ID, and fetch the first date and last date from Table3 against each id.
Scenarios:
If any date of Table3 less than against particular id in Table2 show it as Less
If any date of Table3 equal to against particular id in Table2 show it as Same
If any date of Table3 greater than against particular id in Table2 show it as Greater
Required Output:
ID Value date date1 date2 remarks day_diff
T-1 250 2019-12-10 14:16:19 2019-12-10 14:05:04 2019-12-11 13:12:12 Greater 1
T-2 500 2019-12-11 17:21:05 2019-12-11 14:13:46 2019-12-12 14:05:04 Greater 1
T-3 100 2019-12-12 18:11:01 2019-12-12 14:05:04 2019-12-14 12:18:14 Greater 2
T-4 150 2019-12-13 05:04:11 2019-12-13 01:01:04 2019-12-13 03:03:01 Same 0
T-5 120 2019-12-14 12:10:09 2019-12-15 14:05:04 Null Greater 1
You can use a subquery to generate the MAX and MIN dates from Table3 for each entry in Table2 and then generate the Greater/Same/Less values in an outer query:
SELECT *,
CASE WHEN DATE(date2) > DATE(date) OR DATE(date1) > DATE(date) THEN 'Greater'
WHEN DATE(date2) < DATE(date) OR DATE(date1) < DATE(date) THEN 'Less'
ELSE 'Same'
END AS remarks,
DATEDIFF(date2, date) AS day_diff
FROM (
SELECT t3.ID, t2.Value, t2.date, MIN(t3.date2) AS date1, MAX(t3.date2) AS date2
FROM Table1 t1
JOIN Table2 t2 ON t2.ref_id = t1.ref
JOIN Table3 t3 ON t3.ID = t1.ID
GROUP BY t3.ID, t2.Value, t2.date
) g
Output:
ID Value date date1 date2 remarks day_diff
T-1 250 2019-12-10 14:16:19 2019-12-10 14:05:04 2019-12-11 13:12:12 Greater 1
T-2 500 2019-12-11 17:21:05 2019-12-11 14:13:46 2019-12-12 14:05:04 Greater 1
T-3 100 2019-12-12 18:11:01 2019-12-12 14:05:04 2019-12-14 12:18:14 Greater 2
T-4 150 2019-12-13 05:04:11 2019-12-13 01:01:04 2019-12-13 03:03:01 Same 0
T-5 120 2019-12-14 12:10:09 2019-12-15 14:05:04 2019-12-15 14:05:04 Greater 1
Note that if there is only one date for a Table2 value in Table3, this will give the same values for date1 and date2. If you really want NULL for date2 in that case, change the SELECT * in the above query to
SELECT ID, Value, date, date1,
CASE WHEN date1 = date2 THEN NULL ELSE date2 END AS date2,
Demo on dbfiddle
I have table like below. Where are a lot of rows, which are in different types. I want to select only newest records in each type. There are of course records with different sensor_external_id and sensor_id values.
I need to group both by sensor_id and type. And for that group (sensor_id, type) I need select rows with latest date.
id average date sensor_external_id sensor_id type value
950 2019-10-25 20:34:23 2C3AE834ED58 124 3 25
951 25 2019-10-25 20:34:23 2C3AE834ED58 124 0 25
952 56 2019-10-25 20:34:23 2C3AE834ED58 124 2 56
953 43 2019-10-25 20:34:23 2C3AE834ED58 124 1 41
1411 2019-10-25 20:54:23 2C3AE834ED58 124 3 25
1412 24 2019-10-25 20:54:23 2C3AE834ED58 124 0 23
1413 53 2019-10-25 20:54:23 2C3AE834ED58 124 2 47
1414 41 2019-10-25 20:54:24 2C3AE834ED58 124 1 36
In this case I need exactly that result:
id average date sensor_external_id sensor_id type value
1411 2019-10-25 20:54:23 2C3AE834ED58 124 3 25
1412 24 2019-10-25 20:54:23 2C3AE834ED58 124 0 23
1413 53 2019-10-25 20:54:23 2C3AE834ED58 124 2 47
1414 41 2019-10-25 20:54:24 2C3AE834ED58 124 1 36
I was trying to group by type and date, but without success.
Any ideas?
That's a typical greatest-n per group question. A generic solution that works across most RDBMS with usually good performance is to use a correlated subquery:
select t.*
from mytable t
where t.date = (
select max(t1.date) from mytable t1 where t1.type = t.type
)
For performance, you want an index on (type, date).
If you want the latest record per type and sensor_id, then:
select t.*
from mytable t
where t.date = (
select max(t1.date)
from mytable t1
where t1.type = t.type and t1.sensor_id = t.sensor_id
)
Use row_number()
Select * from( Select *,
row_number() over
(partition by type order by date desc)
from table) rn) t where t.rn=1
I have table like this
user_id order_id create_time payment_amount product
101 10001 2018-04-02 5:26 48000 chair
102 10002 2018-04-02 7:44 25000 sofa
101 10003 2018-04-02 8:34 320000 ac
101 10004 2018-04-02 8:37 180000 water
103 10005 2018-04-02 9:32 21000 chair
102 10006 2018-04-02 9:33 200000 game console
103 10007 2018-04-02 9:36 11000 chair
107 10008 2018-04-02 11:05 10000 sofa
105 10009 2018-04-02 11:06 49000 ac
101 10010 2018-04-02 12:05 1200000 cc
105 10011 2018-04-02 12:12 98000 ac
103 10012 2018-04-02 13:11 85000 insurance
106 10013 2018-04-02 13:11 240000 cable tv
108 10014 2018-04-02 13:15 800000 financing
106 10015 2018-04-02 13:18 210000 phone
my goal is to find which user did transaction consecutively less than 10min.
I'm using mysql
Based on the format of your dates in the table, you will need to convert them using STR_TO_DATE to use them in a query. If your column is actually a datetime type, and that is just your display code outputting that format, just replace STR_TO_DATE(xxx, '%m/%d/%Y %k:%i') in this query with xxx.
The way to find orders within 10 minutes of each other is to self-join your table on user_id, order_id and the time on the second order being within the time of the first order and 10 minutes later:
SELECT t1.user_id, t1.create_time AS order1_time, t2.create_time AS order2_time
FROM transactions t1
JOIN transactions t2 ON t2.user_id = t1.user_id
AND t2.order_id != t1.order_id
AND STR_TO_DATE(t2.create_time, '%m/%d/%Y %k:%i') BETWEEN
STR_TO_DATE(t1.create_time, '%m/%d/%Y %k:%i')
AND STR_TO_DATE(t1.create_time, '%m/%d/%Y %k:%i') + INTERVAL 10 MINUTE
Output:
user_id order1_time order2_time
101 4/2/2018 8:34 4/2/2018 8:37
103 4/2/2018 9:32 4/2/2018 9:36
106 4/2/2018 13:11 4/2/2018 13:18
Demo on dbfiddle
Use this query:
SELECT user_id FROM `table_name` WHERE create_time < DATE_SUB(NOW(), INTERVAL 10 MINUTE) GROUP BY user_id HAVING count(user_id) > 1
I need to get GROUPed BY values,
but I need to see not a random price value (when I select price), but latest price value (price for a row with highest ID within this GROUP)
SELECT ID, price,
ROUND(AVG(price)),
MIN(price),
MAX(price),
ROUND((AVG(price)-MIN(price))/AVG(price) * 100) as differenceinprices
FROM `m-orbitzone`
WHERE dep = 'MOW'
AND returnornot = 1
GROUP BY arv, date1, date2
ORDER BY differenceinprices DESC LIMIT 1000
ID price <-- ROUND(AVG(price)) MIN(price) MAX(price) differenceinprices
122841 834 816 534 834 35
122708 783 790 524 821 34
122754 766 796 529 815 34
28528 810 766 512 810 33
28529 799 765 512 799 33
122603 766 798 534 841 33
122848 766 794 529 810 33
122589 778 765 519 778 32
122591 778 768 519 778 32
122749 766 775 529 814 32
28527 752 749 512 773 32
122744 766 773 529 814 32
122843 766 771 529 802 31
Need 'price' to be latest price for this GROUP (row with highest ID)
May be need to do SELECT and then to do one more SELECT from result?
Thank you!
This should do the trick:
SELECT m.ID, price,
ROUND(AVG(price)),
MIN(price),
MAX(price),
ROUND((AVG(price)-MIN(price))/AVG(price) * 100) as differenceinprices
FROM `m-orbitzone` m
INNER JOIN (
SELECT
ID
FROM
`m-orbitzone` m
WHERE ID = (SELECT MAX(ID) FROM `m-orbitzone` sm WHERE m.arv = sm.arv AND m.date1 = sm.date1 AND m.date2 = sm.date2)
) s ON m.ID = s.ID
WHERE dep = 'MOW'
AND returnornot = 1
GROUP BY arv, date1, date2
ORDER BY differenceinprices DESC LIMIT 1000
A good read about the topic is this manual entry.
I have asked a similar question previously, but posting a new one as I do not want to confuse other
members, and there is an additional column.
What I am looking for is to update the column ItemActual. This needs to be updated with the difference with ItemValue for the latest CurrentTime for the same StartTime if any.
If there is no other entry for the same StartTime other than the current row, it needs to be the ItemValue itself. The comparisons are only to be done for items with the same name.
For eg, Rownum 283, ItemActual = 347013 (since there is no other row with same StartTime).
This applies to row 235 as well, i.e. ItemActual = 1086054.00
For row 190, this needs to be 664031.00 - 533023.00 (comparing with row 145) = 131008
But for row 10, this will be 532023.00, since there is no earlier entry of same item with same StartTime.
Rownum Name ItemValue CurrentTime StartTime
283 ABC 347013.00 3/05/2012 16:01 29/04/2012 6:29
235 ABC 1086054.00 26/03/2012 14:05 7/03/2012 21:18
190 ABC 664031.00 13/02/2012 13:42 29/01/2012 6:39
145 ABC 533023.00 7/02/2012 14:01 29/01/2012 6:39
100 ABC 532023.00 7/02/2012 13:33 29/01/2012 6:39
55 ABC 532023.00 7/02/2012 12:52 29/01/2012 6:39
10 ABC 532023.00 7/02/2012 12:51 29/01/2012 6:39
310 DEF 351012.00 3/05/2012 16:01 29/04/2012 6:29
261 DEF 1339066.00 26/03/2012 14:05 7/03/2012 21:18
215 DEF 785034.00 13/02/2012 13:42 29/01/2012 6:39
170 DEF 620026.00 7/02/2012 14:01 29/01/2012 6:39
You can try something like this:
;WITH PartData AS
(
SELECT
RowNum, Name, ItemValue, CurrentTime, StartTime,
RX = ROW_NUMBER() OVER(PARTITION BY Name,StartTime ORDER BY CurrentTime DESC)
FROM dbo.YourTable
)
SELECT
p1.RowNum, p1.ItemValue, p1.CurrentTime, p1.StartTime,
RowNumComparedTo = p2.RowNum,
ItemActual = CASE
WHEN p2.RX IS NULL THEN p1.ItemValue
ELSE p1.ItemValue - p2.ItemValue
END
FROM PartData p1
LEFT OUTER JOIN PartData p2 ON p1.StartTime = p2.StartTime
AND p1.Name = p2.Name
AND p2.RX = p1.RX + 1
I get an output something like this:
RowNum ItemValue CurrentTime StartTime RowNumComparedTo ItemActual
190 664031.00 2012-02-13 13:42 2012-01-29 06:39 145 131008.00
145 533023.00 2012-02-07 14:01 2012-01-29 06:39 100 1000.00
100 532023.00 2012-02-07 13:33 2012-01-29 06:39 55 0.00
55 532023.00 2012-02-07 12:52 2012-01-29 06:39 10 0.00
10 532023.00 2012-02-07 12:51 2012-01-29 06:39 NULL 532023.00
215 785034.00 2012-02-13 13:42 2012-01-29 06:39 170 165008.00
170 620026.00 2012-02-07 14:01 2012-01-29 06:39 NULL 620026.00
235 1086054.00 2012-05-03 14:05 2012-03-07 21:18 NULL 1086054.00
261 1339066.00 2012-03-26 14:05 2012-03-07 21:18 NULL 1339066.00
283 347013.00 2012-05-03 16:01 2012-04-29 06:29 NULL 347013.00
310 351012.00 2012-05-03 16:01 2012-04-29 06:29 NULL 351012.00
The solution basically does this:
it creates a CTE (Common Table Expression) and "partitions" your data by Name,StartTime and orders these rows by CurrentTime DESC - so the most recent entry for each Name,StartTime group will get an RX (Row indeX) of 1
it then joins that CTE against itself, shifted by one RX - so I'm comparing RX = 1 to RX = 2 (if present) etc.
if a "shifted" row is present, the difference in the ItemValue values is returned as ItemActual - otherwise the ItemValue from the main row is returned
I hope this solves your problem