find consecutive transaction within 10 minutes - mysql

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

Related

Calculate the percentage of success of each measurement values in SQL

I have 3 database tables with sample data given below
Meas_id - integer(Foreign keyed to Measurement.meas_id)
Tool_id - integer(Foreign keyed to Events.Machine_id)
Processdate- Timestamp with timezone (UTC)
CreatedDate- Timestamp with timezone (UTC)
Readings
Meas_id Tool_id Status Processdate
1 13 Completed 2016-01-01 01:34:11
1 28 Failed 2016-01-01 08:37:11
1 54 Failed 2016-01-02 16:04:12
1 32 Completed 2016-01-04 07:13:11
1 39 Completed 2016-01-04 14:14:14
1 12 Completed 2016-01-05 22:10:09
1 9 Completed 2015-12-28 13:11:07
1 17 Completed 2016-01-25 13:14:11
1 27 Completed 2016-01-15 14:15:16
1 31 Failed 2016-01-07 16:08:04
2 113 Completed 2016-01-01 01:34:11
2 128 Failed 2016-01-01 08:37:11
2 154 Failed 2016-01-02 16:04:12
2 132 Completed 2016-01-04 07:13:11
2 139 Completed 2016-01-04 14:14:14
2 112 Completed 2016-01-05 22:10:09
2 90 Completed 2015-12-28 13:11:07
2 117 Completed 2016-01-25 13:14:11
2 127 Completed 2016-01-15 14:15:16
2 131 Failed 2016-01-07 16:08:04
Events
Meas_id Machine_id Event_Name CreatedDate
1 13 Success 2015-12-27 01:34:11
1 17 Error 2015-12-27 08:37:11
1 28 Success 2015-12-27 16:04:12
1 9 Success 2015-12-28 07:13:11
1 54 Success 2015-12-28 14:14:14
1 31 Error 2015-12-28 22:10:09
1 32 Success 2015-12-29 13:11:07
1 39 Success 2015-12-29 13:14:11
1 12 Success 2015-12-31 14:15:16
1 27 Success 2016-01-01 16:08:04
2 113 Success 2015-12-27 01:34:11
2 117 Error 2015-12-27 08:37:11
2 128 Success 2015-12-27 16:04:12
2 90 Success 2015-12-28 07:13:11
2 154 Success 2015-12-28 14:14:14
2 131 Error 2015-12-28 22:10:09
2 132 Success 2015-12-29 13:11:07
2 139 Success 2015-12-29 13:14:11
2 112 Success 2015-12-31 14:15:16
2 127 Success 2016-01-01 16:08:04
Mesurement
Meas_id Meas_name
1 Length
2 Breadth
For each measurement ‘length’ and ‘breadth’ and each day of the week, I am trying to calculate the percentage of success in the first week of 2016 for all completed measurements of tools/machines within 168 hours of thier creation date.
My Desired Output is
Measurement DayofTheWeek PercentageSuccess
Length 1 50
Length 2 0
Length 3 0
Length 4 100
Length 5 100
Length 6 0
Length 7 0
Breadth 1 50
Breadth 2 0
Breadth 3 0
Breadth 4 100
Breadth 5 100
Breadth 6 0
Breadth 7 0
I tried doing it this way but certainly missing some logic and its not working.
Select m.Meas_name,
datepart(dd, Processdate) as DayofTheWeek,
(Count(m.Meas_name)* 100 / (Select Count(Event_Name) From Events where Event_Name = 'Success')) as PercentageSuccess
FROM Readings r JOIN
Measurements m
ON r.Meas_id = m.Meas_id
JOIN Events e
ON e.Meas_id = m.Meas_id
WHERE m.Meas_name IN ('Length', 'Breadth') AND
r.Status = 'Completed' AND
e.CreatedDate >= DATEADD(hh, -168, GETDATE())
GROUP BY m.Meas_name, datepart(dd, Processdate);
Kindly provide inputs on an optimized way of achieving it.
Nice I got downvoted for a correct answer probably because my answer wasn't very clear it is kind of hard to explain so here is an edit aimed at your comment and the downvoter (whom I think was just retaliating).
Anyway, Your joining of 3 tables while valid replicates the data in your events table. Due to that the way you are counting the records will always be exaggerated and incorrect. your calculation for percentage is also happens to be backwards.
On the join it looks like you are just missing the use of the Tool_id in your join. You could try something like the following:
SELECT
m.Meas_name
,DAYOFWEEK(r.ProcessDate) as DayOfTheWeek
,(COUNT(CASE WHEN e.Event_Name = 'Success' tHEN e.Meas_id END)/(COUNT(e.Meas_id) * 1.0)) * 100 as PercentageSuccess
FROM
Measurements m
INNER JOIN Events e
ON m.Meas_id = e.Meas_id
INNER JOIN Readings r
ON e.Meas_id = r.Meas_id
AND e.Machine_id = r.Tool_id
AND r.Status = 'Completed'
AND r.ProcessDate BETWEEN '2016-01-01' AND '2016-01-07'
WHERE
m.Meas_name IN ('Length','Breadth')
GROUP BY
m.Meas_name
,DAYOFWEEK(r.ProcessDate)
Note this is written for mysql because that is what is tagged in you post. if you actually want sql-server as your syntax suggests let me know. Also, I am guessing that you a really want to filter by processdate but if you want to filter by Event.CreateDate then put that in the ON condition of the Events join.

Join Tables Based on Time and ID

I have two tables of time series data that I am trying to query and don't know how to properly do it.
The first table is time series data of device measurements. Each device is associated with a source and the data contains an hourly measurement. In this example there are 5 devices (101-105) with data for 5 days (June 1-5).
device_id date_time source_id meas
101 2016-06-01 00:00 ABC 105
101 2016-06-01 01:00 ABC 102
101 2016-06-01 02:00 ABC 103
...
101 2016-06-05 23:00 ABC 107
102 2016-06-01 00:00 XYZ 102
...
105 2016-06-05 23:00 XYZ 104
The second table is time series data of source measurements. Each source has three hourly measurements (meas_1, meas_2 and meas_3).
source_id date_time meas_1 meas_2 meas_3
ABC 2016-06-01 00:00 100 101 102
ABC 2016-06-01 01:00 99 100 105
ABC 2016-06-01 02:00 104 108 109
...
ABC 2016-06-05 23:00 102 109 102
XYZ 2016-06-01 00:00 105 106 103
...
XYZ 2016-06-05 23:00 103 105 101
I am looking for a query to get the data for a specified date range that grabs the device's measurements and its associated source's measurements. This example is the result for querying for device 101 from June 2-4.
device_id date_time d.meas s.meas_1 s.meas_2 s.meas_3
101 2016-06-02 00:00 105 100 101 102
101 2016-06-02 01:00 102 99 100 105
101 2016-06-02 02:00 103 104 108 109
...
101 2016-06-04 23:00 107 102 109 102
The actual data set could get large with lets say 100,000 devices and 90 days of hourly measurements. So any help on properly indexing the tables would be appreciated. I'm using MySQL.
UPDATE - Solved
Here's the query I used:
SELECT d.device_id, d.date_time, d.meas, s.meas_1, s.meas_2, s.meas_3
FROM devices AS d
JOIN sources AS s
ON d.source_id = s.source_id AND d.date_time = s.date_time AND d.device_id = '101' AND d.date_time >= '2016-06-02 00:00' AND d.date_time <= '2016-06-04 23:00'
ORDER BY d.date_time;
For what its worth, it also worked with the filters in a WHERE clause rather than in the JOIN but it was slower performing. Thanks for the help.

Need help in an Sql Query

I have a fee Table. Whenever a student paying fee it will store in this table.
feeid student_id paid_date received_amount balance_amount next_due_date
3 1 2015-11-07 1000 15000 2015-11-01
5 2 2015-11-07 2000 14000 2015-11-02
9 3 2015-11-07 30000 15000 2015-11-07
11 1 2015-11-07 1000 14000 2015-07-11
12 4 2015-11-07 1000 40000 2015-11-07
13 4 2015-11-07 1000 39000 2015-12-01
14 3 2015-11-07 1000 14000 2015-11-30
15 5 2015-11-09 1000 25000 2015-11-09
16 1 2015-11-09 5000 9000 2015-11-30
17 2 2015-11-09 1000 13000 2015-11-15
18 6 2015-11-10 1000 20000 2015-11-10
19 1 2015-11-11 1000 8000 2015-11-11
20 4 2015-11-11 1000 38000 2015-11-11
21 7 2015-11-11 1000 24000 2015-11-11
22 8 2015-11-11 1000 19500 2015-11-11
23 1 2015-11-14 1000 7000 2015-11-16
So there are more than 1 entries for a single single.I need every students fee details(only last paid details)
Here's one way:
SELECT *
FROM table t1
WHERE paid_date=(SELECT MAX(t2.paid_date)
FROM table t2
WHERE t1.student_id = t2.student_id);
First get all the unique student ids.
After that in a loop
SELECT * FROM table_name WHERE student_id = studentIdFromLoop ORDER BY feeid DESC LIMIT 1
This will give you the last fee record of the every student.

SQL Complex select statement?

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).

MySQL Count Numbers Are Off

I am not sure why my numbers are drastically off from each other.
A query with no max id:
SELECT id, DATE_FORMAT(t_stamp, '%Y-%m-%d %H:00:00') as date, COUNT(*) as count
FROM test_ips
WHERE id > 0
AND viewip != ""
GROUP BY HOUR(t_stamp)
ORDER BY t_stamp ASC;
I get:
1 2012-07-18 19:00:00 1313
106 2012-07-18 20:00:00 1567
107 2012-07-19 09:00:00 847
225 2012-07-19 10:00:00 5095
421 2012-07-19 11:00:00 205
423 2012-07-19 12:00:00 900
461 2012-07-19 13:00:00 619
490 2012-07-20 15:00:00 729
575 2012-07-20 16:00:00 1682
1060 2012-07-20 17:00:00 2063
2260 2012-07-20 18:00:00 1417
5859 2012-07-20 21:00:00 1303
7060 2012-07-20 22:00:00 1340
8280 2012-07-20 23:00:00 1211
9149 2012-07-21 00:00:00 1675
10418 2012-07-21 01:00:00 721
11127 2012-07-21 02:00:00 825
But if I add a max id:
AND id <= 8279
I get:
1 2012-07-18 19:00:00 1313
106 2012-07-18 20:00:00 1201
107 2012-07-19 09:00:00 118
225 2012-07-19 10:00:00 196
421 2012-07-19 11:00:00 2
423 2012-07-19 12:00:00 38
461 2012-07-19 13:00:00 20
490 2012-07-20 15:00:00 85
575 2012-07-20 16:00:00 483
1060 2012-07-20 17:00:00 1200
2260 2012-07-20 18:00:00 1200
5859 2012-07-20 21:00:00 1201
7060 2012-07-20 22:00:00 1220
The numbers are WAY off from each other. Something is goofy.
EDIT: Here is my table structure:
id t_stamp bID viewip unique
1 2012-07-18 19:22:20 5 192.168.1.1 1
2 2012-07-18 19:22:21 1 192.168.1.1 1
3 2012-07-18 19:22:22 5 192.168.1.1 0
4 2012-07-18 19:22:22 3 192.168.1.1 1
You are not grouping by ID and I think you intend to.
Try:
SELECT id, DATE_FORMAT(t_stamp, '%Y-%m-%d %H:00:00') as date, COUNT(*) as count
FROM test_ips
WHERE id > 0
AND viewip != ""
GROUP BY id, DATE_FORMAT(t_stamp, '%Y-%m-%d %H:00:00')
ORDER BY t_stamp;
Your query is not consistent.
In your select statement you are displaying the full date.
But you are grouping your data by the hour. So your count statement is taking the count of all the data for each hour of the day.
As an example take your first result:
1 2012-07-18 19:00:00 1313
The count of 1313 contains the records for all of your dates (7/18, 7/19, 7/20, 7/21, 7/22, etc) that have an hour of 19:00.
But the way you have your query setup, it looks like it should be the count of all records for 2012-07-18 19:00:00.
So when you add AND id <= 8279" The dates of 7/21 and some of 7/20 or no longer being counted so your count values are now lower.
I'm guessing you are meaning to group by the date and hour and not just the hour.