SQL : Fetching new data by date from mysql without iterating in program - mysql

I have a table called student with the structure below. the table represents student visitors to a library.
Id Name Date StudentId
1 John 2010-01-09 3
2 Matt 2010-01-10 5
3 Jane 2010-02-10 8
4 John 2010-02-10 3
5 Matt 2010-02-11 5
6 Jane 2010-02-11 8
7 Bob 2010-02-12 9
8 Tom 2010-02-12 10
9 Sam 2010-02-12 11
10 Jane 2010-02-12 8
I am running a query to fetch New visitors everyday. New visitors are visitors who have never visited the library before that date.The query I am using is as below.
SELECT count(*) FROM student
WHERE DATE(Date) = :date
AND Name NOT IN
(SELECT DISTINCT Name FROM student WHERE DATE(Date) < :date);
I am currently iterating over each date in the table in my program and then using the query above to fetch me New visitors everyday. This works fine but was wondering if it is possible to fetch all values in a single query without iterating in the program? what is more optimal?
the output I am expecting is as below:
Date Count of New Visitors
2010-01-09 1
2010-01-10 2
2010-01-11 0
2010-01-12 3
please note that the below query that I have tried will not fetch the correct result
SELECT Date, Count(*) FROM student
WHERE DATE(Date) BETWEEN :startdate AND :enddate
AND Name NOT IN
(SELECT DISTINCT Name FROM student WHERE DATE(Date) < :startdate) GROUP BY Date;
The result(which is incorrect and what I am not looking for ) I will get from the above query for startdate = 2010-01-09 and enddate = 2010-01-12 is below:
Date Count of New Visitors
2010-01-09 1
2010-01-10 3
2010-01-11 2
2010-01-12 4

You have error in your test output. I think this is what you are looking for:
select u1.date,
(select count(*)
from users u2
where u2.date = u1.date
and u2.studentid not in(select studentid from users u3 where u3.date < u2.date)) c
from users u1
group by u1.date

Related

Mysql return all results matching one column based on a value appearing at least once in another column

I'll try to explain what I need done...I have a table called 'quizzes' with data similar to this:
quiz_id
username
score
5
john
50
5
mary
75
9
mary
20
12
tom
15
12
john
13
12
anne
10
3
john
100
14
john
29
Note - there is only one person per quiz, it's like a record of 'high scores', so no person will have more than one row with a specific quiz_id.
What I want to do is pull all the results where John and at least one other person took that quiz, i.e. 'john' appears as a username and at one other person does too. So, the rows I would want returned are:
quiz_id
username
score
5
john
50
5
mary
75
12
tom
15
12
john
13
12
anne
10
As those are the only quizzes that john and at least one other person took, john didn't take 9, and only john took 3 and 14, so those aren't included either.
I've tried just SELECT quiz_id WHERE username = 'john' but obviously that only returns rows corresponding to his results.
Using a join aggregation approach we can try:
SELECT t1.quiz_id, t1.username, t1.score
FROM yourTable t1
INNER JOIN
(
SELECT quiz_id
FROM yourTable
GROUP BY quiz_id
HAVING SUM(username = 'john') > 0 AND -- john is present
SUM(username <> 'john') > 0 -- someone other than john is present
) t2
ON t2.quiz_id = t1.quiz_id
ORDER BY
t1.quiz_id;

Get last record from joined table

I have two tables DOCUMENT and SIGNATURES, like below
DOCUMENTS
doc_id doc_name
1 Contract
2 Lead
3 Invoice 1
4 Invoice 2
5 Payment 123
SIGNATURES
sig_id sig_doc_id signature_name
1 1 Paul
2 2 Mark
3 1 Chew
4 2 Paul
5 3 John
6 3 Derek
7 3 Silvan
8 5 Roden
And I'm try to get last signature name.
EXPECTED OUTPUT
doc_id doc_name signature_name
1 Contract Chew
2 Lead Paul
3 Invoice 1 Silvan
4 Invoice 2 < empty because we not have signature
5 Payment 123 Roden
I have a SQL FIDDLE with database and query, but when run search no record has found.
http://sqlfiddle.com/#!9/b98474/3
Here my query
SELECT docs.*, sign.*
FROM cnt_man_docs docs
INNER JOIN cnt_man_doc_signatures sign ON docs.cnt_man_doc_id = sign.cnt_man_doc_signature_doc_id
WHERE sign.cnt_man_doc_signature_id =
(SELECT MAX(cnt_man_doc_signature_id)
FROM cnt_man_doc_signatures
WHERE sign.cnt_man_doc_signature_id = docs.cnt_man_doc_id)
A simple method is a correlated subquery:
select d.*,
(select s.signature_name
from signatures s
where s.sig_doc_id = d.doc_id
order by s.sig_id desc
limit 1
) as signature_name
from documents d;
With an index on signatures(doc_id, sig_id desc, signature_name) this is probably the fastest method as well.

Sum values in mysql table where userid is identical

I have read the different answers here on SO, but I am stuck on this question. Please help.
I have this mysql view named "activeuser":
userid COUNT(*) ACRONYM
1 23 admin
2 2 doe
3 4 tompa
12 4 Marre
13 1 Mia
1 2 admin
3 1 tompa
12 1 Marre
13 1 Mia
2 1 doe
3 1 tompa
12 1 Marre
How can I sum the COUNT column so that I get the following wanted result?
userid COUNT(*) ACRONYM
1 25 admin
2 3 doe
3 6 tompa
12 6 Marre
13 1 Mia
EDITED:
I used this query to create the view:
CREATE VIEW activeuser AS
(SELECT boats_comments.userid, COUNT(boats_comments.userid), boats_user.acronym, boats_user.email
FROM boats_comments
INNER JOIN boats_user
ON boats_comments.userid = boats_user.id
GROUP BY boats_comments.userid
ORDER BY COUNT(boats_comments.userid) DESC)
UNION ALL
(SELECT boats_answers.userid, COUNT(boats_answers.userid), boats_user.acronym, boats_user.email
FROM boats_answers
INNER JOIN boats_user
ON boats_answers.userid = boats_user.id
GROUP BY boats_answers.userid
ORDER BY COUNT(boats_answers.userid) DESC)
UNION ALL
(SELECT boats_questions.userid, COUNT(boats_questions.userid), boats_user.acronym, boats_user.email
FROM boats_questions
INNER JOIN boats_user
ON boats_questions.userid = boats_user.id
GROUP BY boats_questions.userid
ORDER BY COUNT(boats_questions.userid) DESC)
My goal is to see which users are the most active by checking the number of comments, questions and answers... but I got stuck...
As the results in your view has duplicates I guess the underlying code for the view is grouping on something it maybe shouldn't be grouping on.
You can get the results you want by applying SUM to it:
select userid, sum("whatever column2 is named") as "Count", Acronym
from activeuser group by userid, Acronym;
select userid, count(*) from activeuser group by userid;

Sum values (same column)

I have this table
user_id time_completed
4 86.30887
5 57.81364
5 35.50281
5 10.00000
5 74.19355
5 31.91489
6 15.00000
6 20.50000
I need to sum all the time for each user, something like this:
user_id time_completed
4 86.30887
5 209.42489
6 35.50000
This is how I get the first table:
$result = mysql_query ("SELECT user_id,time_completed FROM `mytable` ORDER BY `mytable`.`user_id` ASC;" )
Any idea?
EDIT:
What if I need to replace user_id for the name in the following table (db_users)?
id username
1 admin
2 peter
3 tom
4 user
5 joey
6 helen
EDIT2:
I've modified this table (db_users) and I want country also appears in the query.
id username country
1 admin ES
2 peter IT
3 tom US
4 user GB
5 joey GE
6 helen FR
Like this:
user_id time_completed country
4 86.30887 GB
5 209.42489 GE
6 35.50000 FR
Take a look here: http://sqlfiddle.com/#!2/24d1b/11
you need to use SUM() which is an aggregate function and group them by their user_id
SELECT user_ID, SUM(time_COmpleted) totalTime
FROM tableName
GROUP BY user_ID
SQLFiddle Demo
UPDATE 1
SELECT b.username, SUM(time_COmpleted) totalTime
FROM tableName a
INNER JOIN db_users b
ON a.user_id = b.id
GROUP BY b.username
SQLFiddle Demo

MYSQL rating algorithm

I have a MYSQL table which stores a rating for each event of a user, 1-10 in the events table called event_rating. What i'm trying to find is the highest accurate rating based on the number of votes and rating like this:
SELECT
c.userid,
c.user_name,
COUNT(d.event_rating) AS votesCount,
AVG(d.event_rating) AS votesAvg,
SUM(d.event_rating) AS tsum,
COUNT(d.event_rating)*AVG(d.event_rating)/COUNT(d.event_rating) as totalRating
FROM events d JOIN users c ON d.userid = c.userid WHERE (d.userid = '2') GROUP BY d.userid ORDER BY totalRating DESC
I added two dummy ratings for a user, one with a rating of 10 and another with 5.
The results are below:
userid user_name votesCount votesAvg tsum totalRating
2 Rahul Khanna 2 7.5000 15 7.50000000
Is that accurate, and am i calculating it right?
--- EDIT ---
Posting Some more results
USING COUNT(d.event_rating)*AVG(d.event_rating)/COUNT(d.event_rating) as totalRating
userid user_name votesCount votesAvg tsum totalRating
2 Rahul Khanna 2 7.5000 15 7.50000000
1 Rita Agnihotri 9 4.8889 44 4.88888889
3 Daniel Springs 4 3.5000 14 3.50000000
4 Roger Myers 6 3.5000 21 3.50000000
5 Chun Tanakat 3 3.0000 9 3.00000000
USING COUNT(d.event_rating)*AVG(d.event_rating) as totalRating
userid user_name votesCount votesAvg tsum totalRating
1 Rita Agnihotri 9 4.8889 44 44.0000
4 Roger Myers 6 3.5000 21 21.0000
2 Rahul Khanna 2 7.5000 15 15.0000
3 Daniel Springs 4 3.5000 14 14.0000
5 Chun Tanakat 3 3.0000 9 9.0000
--- MORE ---
Should i be using the below instead?
COUNT(d.event_rating)*AVG(d.event_rating)/10 as totalRating
What i need is an accurate way to calculate the total rating, putting votesCount into consideration as well and that the rating has to be between 1-10.
--- MORE DETAIL ---
I have one table Users another Events, user is able to add new events and rate those events. The Events table has a eventID, userid, event_rating column. So each event can hold a rating for the event the user has created. What i want is to calculate all the events rating to get the max (total) rating for that user. I want the total rating i get to be between 1-10 and not exceed over 10 no matter how many events the user has created. Is that possible? if not any solutions or ideas?
Thanks for reading :)
What is this silly piece of query??
COUNT(d.event_rating)*AVG(d.event_rating)/COUNT(d.event_rating) as totalRating
This is nothing
(a*b)/a which is always b
you have to just fetch AVG(d.event_rating)
what do you want really ??