show average time between records groups - mysql

i've a little big puzzle here :)
i've a database with 2 tables: survey_reply and questions,
like this:
table SURVEY_REPLY
id | question_id | data_time | user_id | user reply and others col...
--------------------------------------------------------
522| 2 | 2016-02-29 10:07:10 | jacky
. | 3 | 2016-02-29 10:07:22 | jacky
. | 1 | 2016-02-29 10:07:59 | jacky
.. | 4 | 2016-02-29 10:08:40 | jacky
...| 2 | 2016-02-29 11:21:10 | paul
. | 3 | 2016-02-29 11:21:32 | paul
. | 2 | 2016-02-29 11:21:35 | louise
. | 1 | 2016-02-29 11:21:50 | paul
.. | 4 | 2016-02-29 11:22:30 | paul
.. | 3 | 2016-02-29 11:23:01 | louise
The question are shown to the users following the order in this table:
table QUESTIONS
id | q_ord | survey_id | other columns....
-------------------------------------------
1 | 3 | 786
2 | 1 | 786
3 | 2 | 786
4 | 4 | 786
i would know the average reply time, the time spent by people for make his choice and reply to question.
calculation in this example
4th-3th. (last one minus the previus one)
for reply to question.id=4 (question.q_ord=4)
jacky spent 41 sec (10:08:40-10:07:59)
paul 80 sec (11:22:30-11:21:50)
louise doesnt reply
3th-2nd. (3th one minus the 2nd one)
for the question.id=1 (question.q_ord=3)
jacky spent 37 sec (10:07:59-10:07:22)
paul 18 sec (11:21:50-11:21:32)
louise doesnt reply
2nd-1st.
for the question.id=3 (question.q_ord=2)
jacky spent 12 sec (10:07:22-10:07:10)
paul 22 sec (11:21:32-11:21:10)
louise 86 sec (11:23:01-11:21:35)
i dont need to calculate time for the beginning question.id=2 (question.q_ord=1)
the results should be:
q_id | q_ord | av_reply_time
-------------------------------------------
3 | 2 | (12+22+86)/3
1 | 3 | (37+18)/2
4 | 4 | (41+80)/2
how to figure it out?
PS q_ord it's a consecutive integer numbers without skip any number.
Always begins with 1. I always know the maximum number (total question on the survey) in this case just 4.

I'm assuming that your result set is slightly off, and I can't (yet) see the significance of the second table...
SELECT question_id
, AVG(diff) avg_diff
FROM
( SELECT x.user_id
, x.question_id
, TIME_TO_SEC(TIMEDIFF(MAX(y.data_time),x.data_time)) diff
FROM survey_reply x
JOIN survey_reply y
ON y.user_id = x.user_id
AND y.data_time < x.data_time
GROUP
BY x.user_id
, x.question_id
) a
GROUP
BY question_id;

Related

How can I group by latest dates and IDs, yet take into account all data from previous dates?

So my example table is like this -
I have a mysql version 5.7 database which I can connect to. Read-only rights.
My table goes like this:
human_id | dog_id | dog_bought_at | amount_paid_for_dog | purchase_place | buyer_has_criminal_past
1 | 1 | 27-12-2019 | 100 | Tokyo | 0
1 | 2 | 03-01-2020 | 200 | Moscow | 0
2 | 3 | 03-01-2020 | 200 | Los Angeles | 0
3 | 4 | 03-01-2020 | 50 | Washington | 0
3 | 3 | 05-01-2020 | 30 | Dallas | 0
4 | 2 | 06-01-2020 | 150 | Texas | 1
What I need to show is this:
dog_id | last_owner_id | total_amount_paid_for_dog | last_purchase_date | last_purchase_place
1 | 1 | 100 | 27-12-2019 | Tokyo
2 | 4 | 350 | 06-01-2020 | Moscow
3 | 3 | 230 | 05-01-2020 | Dallas
4 | 3 | 50 | 03-01-2020 | Washington
Last_purchase_place is shown only for those humans, which do not have criminal past.
what I have tried:
SELECT
e.dog_id
,MAX(e.human_id) last_owner_id
,SUM(e.amount_paid_for_dog) total_amount_paid_for_dog
,MAX(e.dog_bought_at) last_purchase_date
,e_filter.purchase_place last_purchase_place
FROM example e
LEFT JOIN (
SELECT
dog_id
,dog_bought_at
,purchase_place
,human_id
FROM example
WHERE buyer_has_criminal_past != 1
) e_filter ON e.dog_id = e_filter.dog_id AND e.dog_bought_at = e_filter.dog_bought_at
But I am stuck on the logic, that allows to sum up ALL amounts, yet filter out unneeded values.
This is my first question here, so if this is a duplicate or not well written, please say it. Any help appreciated.
SELECT e1.dog_id,
e1.human_id last_owner_id,
sq1.total_amount_paid_for_dog,
e1.dog_bought_at last_purchase_date,
e2.purchase_place last_purchase_place
FROM example e1
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at,
SUM(amount_paid_for_dog) total_amount_paid_for_dog
FROM example
GROUP BY dog_id ) sq1 ON e1.dog_id = sq1.dog_id
AND e1.dog_bought_at = sq1.dog_bought_at
LEFT JOIN example e2 ON e1.dog_id = e2.dog_id
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at
FROM example
WHERE buyer_has_criminal_past = 0
GROUP BY dog_id ) sq2 ON e2.dog_id = sq2.dog_id
AND e2.dog_bought_at = sq2.dog_bought_at
fiddle

How to calculate student rank in access

I want to calculate student rank based on their obtmarks as per below tables. Suppose any student scored highest marks in their class but he/she fail in any one subjects then they shouldn't consider for rank.
1. Table name is "resultdata"
Total marks of full marks is(1000)
pass marks is 33
ID | subject ID | subject | fullmarks | obtmarks |passmarks
1 | 1 | HINDI | 100 | 80 | 33
2 | 2 | ENGLISH | 100 | 90 | 33
3 | 3 | MATHEMATICS | 100 | 76 | 33
4 | 4 | SOCIAL SCIENCE| 100 | 69 | 33
like that others subjects also.
2. Table name is "result"
ID|result | student |student|mother |father |class|term/ |rollno|section|
|date | ID |name |name |name | |semester | | |
1 |11.09.2019| 1 |Jasmine|Eliana |Ritesh | 8 |1st Term | 10 | A |
2 |11.09.2019| 2 |Kiyas |Fanny |Rajnish| 10 |1st Term | 1 | B |
3 |11.09.2019| 3 |Ena |Rashmi |Prakash| 9 |1st Term | 12 | C |
4 |11.09.2019| 4 |Sunaina|Ankita |Chander| 7 |1st Term | 15 | A |
5 |11.09.2019| 5 |Ankit |Sujata |Roy | 8 |1st Term | 11 | B |
6 |11.09.2019| 6 |Krishna|Bala |Gopal | 8 |1st Term | 5 | C |
7 |11.09.2019| 7 |Ranga |Hima |Hitesh | 9 |1st Term | 7 | A |
8 |11.09.2019| 8 |Suraj |Priya |Hemal | 7 |1st Term | 10 | B |
9 |11.09.2019| 9 |Saurabh|Archana|Suyog | 10 |1st Term | 9 | B |
3. Table name is "subjects"
ID | subject | fullmarks | passmarks
1 | HINDI | 100 | 33
2 | ENGLISH | 100 | 33
3 | MATHEMATICS | 100 | 33
4 | SOCIAL SCIENCE | 100 | 33
5 | Computer | 50 | 20
like that others subjects also.
ID of subjects table and subjectID of resultdata table has relationship.
How to resolve this issue using a formula or vba code?
Condition1: Calculate every student rank on basis of their total obtained marks. But any student has failed in any subjects they will not consider for TOP 10 rank.
Condition 2: Calculate every student rank on basis of their total obtained marks.
I tried this formula in query but it does not work:
Rank: DCount("*","resultdata","[fullmarks]>" & [obtmarks])+1
If you don't want to include students with any failing grade then do a preliminary query to eliminate them. Then use that query to rank the remaining students. Consider:
Query1: Passing
SELECT resultdata.StudentID, Sum(resultdata.obtmarks) AS SumOfobtmarks
FROM resultdata
GROUP BY resultdata.StudentID
HAVING resultdata.StudentID Not In (SELECT resultdata.StudentID
FROM resultdata
WHERE resultdata.obtmarks<[passmarks]);
Query2:
SELECT Passing.SumOfobtmarks, Passing.StudentID,
(SELECT Count(*) FROM Passing AS T1 WHERE T1.SumOfobtmarks > Passing.SumOfobtmarks)+1 AS Rank
FROM Passing
ORDER BY Passing.SumOfobtmarks DESC;
However, if multiple students have same score, results will likely not be satisfactory. This is a common topic with many examples. For one review http://allenbrowne.com/ranking.html. Best solution might be one involving a 'temp' table as explained in Allen's article. Or try Lebans Serialize function, link is in Allen's article. Another excellent tutorial demonstrating these techniques http://www.mendipdatasystems.co.uk/rank-order-queries/4594424063.

mysql combine 2 table with a common group by column

i've 2 tables with date, in timestamp format,
i have to count how many record there are every week in total...
...and have the result in just one query...
so i'll explain it better with examples:
2 table, the first one:
table name: visitor
ID | time | ref (now i put in fake timestamp in time column sorry)
--------------------
1 | 3455 | john
2 | 3566 | ted (week 40)
3 | 8353 | ted (week 38)
4 | 6673 | katy
5 | 6365 | ted (week 40)
6 | 4444 | john
7 | 3555 | ted (week 40)
and the second one (very similar):
table name: users
ID | time | ref (now i put in fake timestamp in time column sorry)
--------------------
1 | 3455 | ted (week 41)
2 | 3566 | ted (week 42)
3 | 8353 | ted (week 40)
4 | 6673 | katy
5 | 6365 | ted (week 41)
6 | 4444 | john
7 | 3555 | ted (week 38)
8 | 6789 | ted (week 43)
i do this query and i obtain this result:
SELECT WEEK(FROM_UNIXTIME(time)) AS week, COUNT( * ) AS tot
FROM visitor WHERE ref='ted' GROUP BY week
table result #1
week | tot
----------
38 | 1
40 | 3
43 | 1
the i do the some for the second table:
SELECT WEEK(FROM_UNIXTIME(time)) AS week, COUNT( * ) AS totuser
FROM users WHERE ref='ted' GROUP BY week
table result #2
week | totuser
----------
38 | 1
40 | 1
41 | 2
42 | 1
but i want with just one query do this result:
week | tot | totusers
---------------------- (when both are 0 doent appear -like 39 for example-)
38 | 1 | 1
40 | 3 | 1
41 | 0 | 2
42 | 0 | 1
43 | 1 | 0
i know that i've to use LEFT JOIN, GROUP BY and IFNULL but i'm doing always something wrong and i cant figure it out.
order by WEEK desc
thank u for any help.
Technically, what you want is a full outer join, but MySQL does not support that. I approach this using union all and group by:
SELECT weeek, SUM(visitors) as visitors, SUM(users) as users
FROM ((SELECT WEEK(FROM_UNIXTIME(time)) AS week, COUNT( * ) AS visitors, 0 as users
FROM visitor
WHERE ref='ted'
GROUP BY week
) UNION ALL
(SELECT WEEK(FROM_UNIXTIME(time)) AS week, 0, COUNT( * )
FROM users
WHERE ref ='ted'
GROUP BY week
)
) w
GROUP BY week
ORDER BY week;
Note: As in your data, this will only include weeks that have either visitors or users. If you want weeks with neither, it is best to start with a table containing all the weeks you want (some sort of calendar table).

Get 2 latest records and do a math function

So i have a table called Ronde:
ID | Teamid | Timestamp
----------------------------------------
1 | 1 | 2013-06-28 18:35:28
2 | 1 | 2013-06-28 18:36:28
3 | 2 | 2013-06-28 18:36:30
4 | 3 | 2013-06-28 18:37:28
5 | 2 | 2013-06-28 18:40:28
6 | 1 | 2013-06-28 18:42:28
7 | 2 | 2013-06-28 18:43:28
8 | 3 | 2013-06-28 18:48:28
Here's a sqlfiddle of same.
So what i need is a query who takes the 2 newest records grouped by Teamid and do a math function with timestamp.
So example:
newest1, newest2
result = ( 60 minutes / (newest2.timestamp - newest1.timestamp) ) * 6
The result is the avg speed between 2 timestamps.
`LIMIT` in subquery don't work
Someone have a solution for my problem ???
Desired output data :
Teamid | Speed
1 | 60
2 | 120
3 | 32,72
Maybe something like this....
http://www.sqlfiddle.com/#!2/2dc3f/7
?

MySql selecting greatest difference between 2 rows within the past day

I have a table that sort of looks like this
id | name | c1 | c2 | c3 | c4 | time
-------------------------------------------------
1 | miley | 23 | 11 | 21 | 18 | 2013-01-13 20:26:25
2 | john | 31 | 29 | 23 | 27 | 2013-01-14 20:26:25
3 | steve | 44 | 31 | 33 | 35 | 2013-01-14 20:26:25
4 | miley | 34 | 44 | 47 | 48 | 2013-01-15 08:26:25
5 | john | 27 | 53 | 49 | 52 | 2013-01-15 08:26:25
6 | steve | 27 | 62 | 50 | 64 | 2013-01-16 08:26:25
7 | miley | 44 | 54 | 57 | 87 | 2013-01-16 20:26:25
8 | john | 37 | 93 | 59 | 62 | 2013-01-17 20:26:25
9 | steve | 85 | 71 | 87 | 74 | 2013-01-17 20:26:25
...etc
*note: this is a random table I made up to just give you an idea of what my table looks like
I need to grab the name for who had the greatest change in a specific column over the course of a specific date range. I've tried a bunch of different queries by can't get one to work. I think my closest solution is something like...
SELECT table1.name, MAX(table1.c1-h.c1) as maxDiff
FROM table_a as table1
LEFT JOIN table_a as table2
ON table2.name=table1.name AND table1.c1>table2.c1
WHERE table2.c1 IS NOT NULL
What am I doing wrong? To be clear, I want to be able to select a range of dates then determine who has the biggest difference for that date range in a determined column. Also note that the data only increments over time, so the first capture of any day will always be <= the last capture of the day for that person.
It sounds like you will be needing a nested query. First, a query of each person on their own measurements within the date range, then order it by the biggest and take the top 1... something like this may work for you...
select
PreGroupByName.`Name`,
PreGroupByName.MaxC1 - PreGroupByName.MinC1 as MaxSpread
from
( select
t1.`Name`,
min( t1.c1 ) as MinC1,
max( t1.c1 ) as MaxC1
from
table_a t1
where
t1.`time` between '2013-01-01' and '2013-01-17' -- or whatever date/time range
group by
t1.`Name` ) as PreGroupByName
order by
MaxSpread DESC
limit 1
SELECT
`id`,`name`
,MAX(`c1`)-MIN(`c1`) AS `diff_c1`
-- ,MAX(`c2`)-MIN(`c2`) AS `diff_c2`
-- ,MAX(`c3`)-MIN(`c3`) AS `diff_c3`
-- ,MAX(`c4`)-MIN(`c4`) AS `diff_c4`
FROM `the_table`
WHERE `time` BETWEEN '2013-01-13 20:26:25' AND '2013-01-17 20:26:25'
GROUP BY `name`
ORDER BY `diff_c1` DESC -- whichever you want to evaluate
LIMIT 1