This is my first post, so please forgive me for any formatting errors.
I need to find the time between each row of data for a large number of users, and then take the average of those times as a function of time. I know how to to do the latter part, I just don't know how to find the time differences between rows.
For example, I can generate this output very easily (for all users sequentially, just using 'John' as an example):
User order time
John 13 2013-10-31 22:35:19
John 12 2013-10-18 23:16:50
John 11 2012-12-07 00:38:34
John 10 2012-06-10 02:19:14
John 9 2010-07-02 00:55:54
John 8 2009-12-20 23:43:41
John 7 2009-12-20 01:14:32
John 6 2009-12-18 15:12:40
John 5 2009-12-13 00:38:38
John 4 2009-12-12 16:00:13
John 3 2009-12-12 14:50:18
John 2 2009-12-11 18:41:15
John 1 2009-12-04 03:12:06
But, what I need to find out how to do is create this:
User order time timeDiff
John 13 2013-10-31 22:35:19 13
John 12 2013-10-18 23:16:50 300
John 11 2012-12-07 00:38:34 170
John 10 2012-06-10 02:19:14 ...
John 9 2010-07-02 00:55:54 ...
John 8 2009-12-20 23:43:41 ...
John 7 2009-12-20 01:14:32 ...
John 6 2009-12-18 15:12:40 ...
John 5 2009-12-13 00:38:38 ...
John 4 2009-12-12 16:00:13 ...
John 3 2009-12-12 14:50:18 ...
John 2 2009-12-11 18:41:15 ...
John 1 2009-12-04 03:12:06 NULL
This is easily done in excel, but I need the grouping properties for users + dates in order to do some analysis.
All help appreciated!!
Try this
Select current.time - previous.time As TimeDiff
From UserTable current Join
UserTable previous On current.User = pervious.User And current.Order - 1 = previous.Order
Where current.User = 'John'
That should get you the time differences.
You said you knew how to get the average from there.
Like you said, it's easy in Excel. Referring to relative rows in SQL is pretty hard, especially in MySQL.
You have to use server-side variables to establish "state", so you can remember previous values. e.g.
SET prev := null;
SELECT User, Order, time, IF(#prev IS NOT NULL, time - #prev, null), #prev := time;
It gets even harder since you're doing this for multiple users, and will have to add extra code to detect when the user changes.
For this kind of thing, you're better off doing the calcs in client-side code. Which means just do:
SELECT User, Order, UNIX_TIMESTAMP(time)
...
ORDER BY User, Order
and then you can feed those timestamps directly to PHP's time system for formatting/calculations.
Related
Sounds simple but I couldn't find the solution for it.
I have a table with 3 columns. Account, Amount, Date.
I want to get all entries except the ones of one specific account with negative amount. But I still want to get the entries of this account if amount value is positive.
So with this query I'm also not getting the entries from account1 with a positive amount.
select * from table where (account!='account1' AND amount<='0') AND date='2020-05-01'
You can do this using WHERE NOT in your statement.
Example schema:
Account Amount Date
=====================================
1 Ben 200 2020-10-10
2 Frank 200 2020-10-10
3 Ben -300 2020-10-12
4 Ben 10 2020-10-16
5 Mary 2000 2020-10-16
6 Frank -200 2020-10-18
7 Ben -10 2020-10-18
8 Ben 0 2020-10-20
Now if you build your query like this
SELECT * FROM t1 WHERE NOT (account='Ben' AND amount<0);
you should get what you want (all records except the 3rd and 7th).
Edit: if you really only want to exclude records with negative amounts, you need to do < rather than <= as you did in your example above. Depends on whether you want row 8 to be included in the result or not.
I have a database about sports event that contains:
*User ID
*Amount of Points that the user got on that event
*Time (HH:MM:SS) that took the user to complete track.
How can I first sort them by no. of points, then if two users have same amount of points, by time (shorter is better); and then insert the places to rows?
I have database like that:
ID No. of Points Time Place
------------------------------------
1 15 00:56:00
2 13 00:55:15
3 17 01:00:00
4 17 00:57:00
5 19 00:52:15
I need to have it with places:
ID No. of Points Time Place
------------------------------------
1 15 00:56:00 4
2 13 00:55:15 5
3 17 01:00:00 3
4 17 00:57:00 2
5 19 00:52:15 1
I hope, you understand that. Sorry for bad English.
Best regards,
You can do this with update statement as follows.
SET #placeValue:=0;
UPDATE [Table Name] SET Place=#placeValue:=#placeValue+1 ORDER BY
[Amount of Points] DESC,Time ASC
I have a question, and I don't know if its possible to solve.. I break my mind, and don't discover a solution..
I have a table and I Select the new registers that I don't select last time that the admin has logged in.
No problem.
With this "new registers" I send a gift.
but ONLY if its the FIRST TIME of the user in my website.
(The table is a Training Table - the users made the lesson - register your participation - and If its your first time - I sent a Welcome kit. If he is a returning user, I don't sent the kit again)
LESSON is not sequential (You can make Lesson 2 first)
============================
USERID LESSON TIME
222 2 2016-04-01
122 1 2016-04-01
122 3 2015-10-20
In this table I select ALL USERS with TIME = 2016-04-01 (last registers)
============================
USERID LESSON TIME
222 2 2016-04-01
122 1 2016-04-01
but.. USERID 122 had made another lesson last year (and receive the welcome kit)
Then, the answer is: (only 222 is a "REAL NEW" user)
============================
USERID | LESSON | TIME
222 | 2 | 2016-04-01
Thanks!!
You can use NOT EXISTS for this:
SELECT USERID, LESSON_TIME
FROM REGISTERS AS r1
WHERE LESSON_TIME = '2016-04-01' AND
NOT EXISTS (SELECT *
FROM REGISTERS AS r2
WHERE r1.USERID = r2.USERID AND
r2.LESSON_TIME < r1.LESSON_TIME)
I have table with ID DOB AMOUNT RECEIVER_NAME SENDER_NAME SETTLE_FEE columns.
Sample Data
ID DOB AMOUNT RECEIVER_NAME SENDER_NAME SETTLE_FEE
-------------------------------------------------------------------
1 10-06-1990 100 Jose Benn 12
2 12-06-1990 200 Jim Mike 12
3 10-06-1990 300 Kate Benn 12
4 12-06-1990 100 Amy Mike 12
5 10-06-1990 200 Alison Benn 12
6 12-06-1990 300 Mary Mike 12
Expected result
ID DOB SENDER_NAME
---------------------------
1 10-06-1990 Benn
|--------AMOUNT RECEIVER_NAME SETTLE_FEE
100 Jose 12
300 Kate 12
200 Alison 12
2 12-06-1990 Mike
|--------AMOUNT RECEIVER_NAME SETTLE_FEE
200 Jim 12
100 Amy 12
300 Mary 12
I need to get all the data of each sender name.
I tried using group_concat(), But, it can take only 1024 characters.
So, what is the efficient way to achieve this scenario.
I can't use PL/SQL and no session related values allowed.
I need all the receiver's name, amount, fee for all the sender_name. What is the efficient way to do it.
Thanks,
Jose
There is a solution:
Just use an ORDER BY:
SELECT ID, DOB,SENDER, AMOUNT, RECEIVER_NAME, SETTLE_FEE
FROM inputTable
ORDER BY SENDER,DOB;
In displaying as you want the data, you just use code like (dummy code, javscriptish):
var previousSender="";
while(var row=db.fetch()) {
if(row.sender!=previousSender) {
console.log(id+" "+row.dob+" "+row.sender);
previousSend=row.sender();
} else {
console.log(" |-------"+row.amount+" "+row.receiver_name+" "+row.settle_fee);
}
}
As you can see: id is random since it has no relation to the dob or sender in your model. It is just a row counter.
I have this sql table with people's name and ages.
Bob 28
Bryan 30
Jim 25
John 42
Bill 22
Sam 28
Tom 26
I would like to make a sql command to order all people by age desc, find a name in it, a return the preceding one, the founded and the next one with their position.
For example, admit that I would like to find Tom, my request should return :
Name Age Rank
Jim 25 2
Tom 26 3
Bob 28 4
Jim has the number 2 because Bill is the youngest
Is it possible to do something like this ?
Thanks in advance for any help
SQL isn't suited for row-based operations. There's no easy way to do "find a row where some condition(s) = true, then return the previous row" in a single query. You can do it in a couple steps, though:
a) Run one query to retrieve 'Tom' and his age (26).
b) Run another query to get the next older person
SELECT name, age FROM ... WHERE age > 26 ORDER BY age ASC LIMIT 1
c) Repeat but for next younger:
SELECT name, age FROM ... WHERE age < 26 ORDER BY age DESC LIMIT 1
This'll fetch people who are at least 1 year old/younger... You don't specify what happens if there's multiple people of the same age (e.g. There's Fred who's also 26, or Doug and Elmer who are both 25), so I'm ignoring those conditions.