Moodle Dates When User Completed Course - mysql

I am trying to get the dates for when a user has last completed the course, I have the following working SQL but its giving the wrong dates.
I have dates for all modules, but know they are wrong as there a couple of months old, and I know 1 course was completed yesterday.
SELECT
u.username,
c.shortname,
DATE_FORMAT(FROM_UNIXTIME(gi.timemodified), '%d/%m/%Y') AS 'date'
FROM moodle.user u
JOIN moodle.grade_grades g ON g.userid = u.id
JOIN moodle.grade_items gi ON g.itemid = gi.id
JOIN moodle.course c ON c.id = gi.courseid
WHERE u.email = ?
GROUP BY c.shortname

The course completions should be in mdl_course_completions
SELECT u.username,
c.shortname,
cc.timecompleted
FROM mdl_course_completions cc
JOIN mdl_course c ON c.id = cc.course
JOIN mdl_user u ON u.id = cc.userid
WHERE u.email = :email

Related

Sub query within SELECT statement always returning NULL

I am trying to write an SQL SELECT statement with a sub query. There is no error returned but I don't get the results I am expecting. The value for r.related is always NULL.
SELECT
l.id,
u.id as user_id,
u.name,
r.related
FROM
list l
INNER JOIN user u ON u.id = l.user_id
LEFT JOIN (
SELECT COUNT(u.id) AS related, b.group_id
FROM user u
INNER JOIN booking b ON b.user_id = u.id
WHERE u.id != l.user_id
AND b. = 0) AS r ON r.group_id = l.group_id
WHERE
l.group_id = 22
GROUP BY l.id, u.id
ORDER BY l.id
I am writing the sub query correctly?
Here's the problem:
SELECT COUNT(u.id) AS related, b.group_id
FROM user u
INNER JOIN booking b ON b.user_id = u.id
WHERE u.id != b.user_id
AND b. = 0
Look, you are joining user and booking table on booking.user_id = user.id
and
then you are just discarding those matching rows between these two tables in your where condition WHERE user.id != booking.user_id;
It's more like you are looking the differences between Set A and Set B in A intersection B. So in this case you won't find any (i.e. NULL).

SQL Join with MAX().

I have two tables, users and contestants. I'm trying to select the max contestant ID that has a profile picture(which is on the user table)
Heres my terrible SQL:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
The error currently is: #1248 - Every derived table must have its own alias.
This confuses me since Users has an alias of u, and contestants has an alias of c..
What am I doing wrong here? I'm guessing a lot so some help would be really appreciated!
Whenever you are performing a join operation, you are actually joining two table. The subquery you wrote here, for instance, is working as a separate table. Hence, you have to use an alias to this table. That's the reason behind your error message.
Your query:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
It should contain an alias for the subquery:
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
Let's say, it's T.
So, your query now becomes:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) AS T
WHERE u.thumbnail IS NOT NULL
But what you are trying to achieve, can actually be done in a neater way:
SELECT u.thumbnail, u.id, max(c.id),
FROM users as u
LEFT JOIN contestants as c
on u.id = c.user_id
WHERE u.thumbnail IS NOT NULL
Why make all the fuss when you have a better and neater approach at your disposal?
try this:
SELECT u.thumbnail, u.id
FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
)A
WHERE u.thumbnail IS NOT NULL
i think this should be simple,
SELECT u.thumbnail, u.id
FROM users u
INNER JOIN contestants c
ON u.id = c.users_id
WHERE u.thumbnail IS NOT NULL
ORDER BY c.id DESC
LIMIT 1
This is very simple.
SELECT user.thumbnail, user.id
FROM users user
INNER JOIN contestants cont ON cont.id = cont.users_id
WHERE cont.thumbnail IS NOT NULL
ORDER BY user.id DESC

MySQL select where no matches in join

How would I do following in MySQL:
I have 3 tables:
user: id
communication: id, creation_date
user_communication: user_id, communication_id
Now I want to select all users that have had no communication since a given date.
Following is what I have now, but I'm stuck on how to get what I described above.
SELECT DISTINCT u.id FROM user u
LEFT JOIN user_communication uc ON uc.user_id = u.id
LEFT JOIN communication c ON c.id = uc.communication_id
WHERE c.creation_date < '2013-8-1';
The where condition is undoing the left join. The initial solution would be to move it to the on clause:
SELECT DISTINCT u.id FROM user u
LEFT JOIN user_communication uc ON uc.user_id = u.id
LEFT JOIN communication c ON c.id = uc.communication_id and c.creation_date < '2013-8-1';
But this doesn't do what you want. This retrieves all records. If you had a creation date field in the select clause, it would be NULL when there is record before that date.
For no communication since that date, you can do a "double" negative" query. Look for records that are since that date, and return the mismatches:
SELECT DISTINCT u.id
FROM user u LEFT JOIN
user_communication uc
ON uc.user_id = u.id LEFT JOIN
communication c
ON c.id = uc.communication_id and c.creation_date >= '2013-08-01'
WHERE c.creation_date is NULL;
EDIT:
I see. The problem is a little more subtle than my answer above. Each user has multiple communications, so none can be later. The following query tests this by grouping by u.id and then checking that there are no non-NULL values from the above join:
SELECT u.id
FROM user u LEFT JOIN
user_communication uc
ON uc.user_id = u.id LEFT JOIN
communication c
ON c.id = uc.communication_id and c.creation_date >= '2012-08-01'
group by u.id
having min(c.creation_date is null) = 1;
SELECT DISTINCT u.id FROM user u
LEFT JOIN user_communication uc ON uc.user_id = u.id
LEFT JOIN (SELECT * FROM communication WHERE creation_date < '2013-8-1') c
ON c.id = uc.communication_id
WHERE c.id is NULL;
After some research and help I have following query, which seems to work:
SELECT DISTINCT(u.id)
FROM user u
WHERE (SELECT coalesce(max(c.creation_date), '1900-01-01 00:00:00') last_creation_date
FROM user inneru
LEFT JOIN user_communication uc ON uc.user_id = inneru.id
LEFT JOIN communication c ON c.id = uc.communication_id
WHERE inneru.id = u.id) < '2012-08-01'
SQLFiddle: http://sqlfiddle.com/#!2/5dfad/10

msql wrong total and sum on result

We have three different following tables...
users
id,
username
password
email
user_clubs
id,
user_id,
club_name
sales
id,
club_id,
amount,
admin_fees,
dnt
And we want to get total sum of admin_fees as outstanding for user_id(for example 55), so we tried following...
SELECT u.id, count(c.id), SUM(s.admin_fees) as total_admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
WHERE u.id = 55
GROUP BY u.id;
But its returning value of first row, so balance is not correct, Please help to resolve.
Try this:
SELECT g.id, count(g.club_id), SUM(g.admin_fees) AS total_admin_fees
FROM (
SELECT u.id, c.id AS club_id, s.admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
WHERE u.id = 55
) AS g
GROUP BY g.id;

mysql sum using left join on three tables

We have following tables...
users
id, username password email
user_clubs
id, user_id, club_name
sales
id, club_id, amount, admin_fees, dnt
We are trying to get total sum of admin_fees as outstanding for user_id(for example 5), and we tried following...
SELECT u.id, count(c.id), SUM(s.admin_fees) as total_admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
WHERE u.id = 5
GROUP BY u.id;
Which is only returning results for first row, which is incorrect, Please help to resolve.
here is sql fiddle to test.
thanks
Try this one for user_id = 5 there are two club ids and with amount 2,5 so total should be 7
SELECT u.id, COUNT(c.id), SUM(s.admin_fees) AS total_admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
WHERE u.id = 5
GROUP BY s.club_id;
for all users you can do this
SELECT u.id, COUNT(c.id), SUM(s.admin_fees) AS total_admin_fees
FROM users u
LEFT JOIN user_clubs c ON c.user_id = u.id
LEFT JOIN sales s ON s.club_id = c.id
GROUP BY u.`id`;
Fiddle