Mysql request from two tables with counting - php

I have two tables
**users**
id name
1 Name1
2 Name2
**tasks**
id user_id title
1 1 Task1
2 1 Task2
3 2 Task3
My request:
SELECT
U.*,
COUNT(T.id) AS tasks_total
FROM
`#__users` AS U
LEFT JOIN
`#__tasks` AS T
ON
U.id = T.user_id
I think something wrong here...
I wan't to get results:
id name tasks_total
1 Name1 2
2 Name2 1
Thanks!

You forgot to group the result by id
SELECT
U.*,
COUNT(T.id) AS tasks_total
FROM
`#__users` AS U
LEFT JOIN
`#__tasks` AS T
ON
U.id = T.user_id
group by U.id
demo on sqlfiddle

You're mixing line functions and aggregate functions. One way around this is to have the aggregation done in a subquery:
SELECT
U.*,
tasks_total
FROM
`#__users` AS U
LEFT JOIN
(SELECT user_id, COUNT(*) AS tasks_total
FROM `#__tasks`
GROUP BY user_id) AS T
ON
U.id = T.user_id

Related

How to select latest records from multiple tables Mysql Php

I have three tables and i want to get records according to datetime for all tables,
Here is my table "users"
id name
1 abc
2 xyz
Here is my table "paymentHistory"
id bookingId userId createdOn
1 101 1 2020-07-10 12:11:14
2 102 1 2020-07-11 10:31:19
3 105 1 2020-07-11 12:31:19
4 109 2 2020-07-10 11:45:32
Here is my table "cancelPaymentHistory"
id bookingId userId createdOn
1 103 1 2020-07-07 11:31:28
2 100 1 2020-07-11 11:31:28
3 109 2 2020-07-08 19:28:41
Here is my table "usr_booking"
id bookingId userId status created_on
1 104 1 Inprocess 2020-07-07 10:31:28
Now i want to get all record where userId='1' and according to createdOn (DESC) of three tables
How can i do this ?
I tried with following code but showing so many records( showing wrong result)
SELECT u.id as userId,ph.bookingId as paymentHistoryBooking,cph.bookingId as CancelBookingId,ub.bookingId as usrBooking
FROM users u
JOIN paymentHistory ph ON u.id=ph.userId
JOIN cancelPaymentHistory cph ON u.id=cph.id
JOIN usr_booking ub ON u.id=ub.userId
WHERE u.id='152'
Your query is not correct.
First you miss the alias u of the users table so the second row must look like:
FROM users u
Second, in the the fourth row you accidently wrote u.id = cph.id, but you want to match with the userId, not the cancelPaymentHistory.id. Additionally you miss the alias for the cancelPaymentHistory table. So the correct fourth line must look like:
JOIN cancelPaymentHistory cph ON u.id = cph.userId
The whole query would look like:
SELECT u.id as userId,ph.bookingId as paymentHistoryBooking,cph.bookingId as CancelBookingId,ub.bookingId as usrBooking
FROM users u
JOIN paymentHistory ph ON u.id=ph.userId
JOIN cancelPaymentHistory cph ON u.id=cph.userId
JOIN usr_booking ub ON u.id=ub.userId
WHERE u.id='152';
To order your result by the latest createdOn of all tables, you must first identify the latest createdOn of all tables:
SELECT userId, max(createdOn) as latestActivity
(SELECT userId, max(createdOn) as createdOn
FROM cancelPaymentHistory
UNION
SELECT userId max(createdOn) as createdOn
FROM usr_booking
UNION
SELECT userId max(createdOn) as createdOn
FROM paymentHistory)
This result must be joined with the prior query:
SELECT u.id as userId,ph.bookingId as paymentHistoryBooking,cph.bookingId as CancelBookingId,ub.bookingId as usrBooking
, max(latestActivity)
FROM users u
JOIN paymentHistory ph ON u.id=ph.userId
JOIN cancelPaymentHistory cph ON u.id=cph.userId
JOIN usr_booking ub ON u.id=ub.userId
JOIN (SELECT userId, max(createdOn) as latestActivity
FROM (SELECT userId, max(createdOn) as createdOn
FROM cancelPaymentHistory
UNION
SELECT userId, max(created_on) as created_on
FROM usr_booking
UNION
SELECT userId, max(createdOn) as createdOn
FROM paymentHistory) a) activity ON activity.userId = u.id
WHERE u.id='1'
ORDER BY activity.latestActivity DESC;
Note, that I still got the ORDER BY in the query. I am assuming you want to run this statement for multiple users, so you can modify the WHERE-Statement like
WHERE u.id IN ('1','2','3') and still have a sorted list.
I have set up a fiddle for you http://sqlfiddle.com/#!9/ea835a/28/0

not able to select count with case condition

I have the two tables:
user_groups
id name created_user
1 gn1 3
2 gn2 3
user_group_has_users
group_id user_id
2 5
2 6
I want to count the users per group and an output similar this:
id name user_count
2 gn2 2
1 gn1 0
I tried this query
select g.*,
count(cg.user_id) as user_count
from user_groups as g
left join user_group_has_users as cg on cg.user_group_id = g.id
where g.created_user = 3
But it only returns one row. I do not understand why this happening.
Please help me on this.
Use this query
SELECT g.* ,COUNT(cg.user_id) AS user_count
FROM user_groups g
LEFT JOIN user_group_has_users cg ON cg.group_id = g.id
WHERE g.created_user = 3
GROUP BY g.id
ORDER BY user_count DESC ;
Left join with where condition is nothing but inner join. You may want as
select
ug.id,
ug.name,
count(ughu.user_id) as user_count
from user_groups ug
left join user_groups_has_users ughu on ughu.group_id = ug.id
and ug.created_user = 3
group by ug.id
order by user_count desc ;
If you still want to filter the data with the created_user = 3 then use inner join and move the condition to where clause
Be careful with aggregates and JOINs. In some cases the numbers are inflated.
See if this works for you:
select g.*,
( SELECT count(*)
FROM user_group_has_users
WHERE user_group_id = g.id
) AS user_count
from user_groups as g
where g.created_user = 3

Slow query using "where in" and "order by select count"

I want to show post from users that specified user is followed and i have two tables at below. but its query is very slow.
table user
id | username
1 | name1
2 | name2
3 | name3
..
..
table post
id | poster_id | post_content
1 | 2
2 | 3
3 | 10
..
..
table follow
followerid | followtoid
1 | 2
1 | 3
2 | 10
..
..
Assume that all tables have more than 1000 rows.
This's SQL
SELECT *
FROM post
WHERE poster_id IN (
SELECT followtoid
WHERE followerid = $_SESSION['userid']
)
And this's the second cast is very slow too.
I want to list all member by order from their total posts.
SELECT *
FROM user
ORDER BY (
SELECT COUNT(id)
FROM post
WHERE post_id = user.id
) DESC;
Try indexing post.userid, post.poster_id, followtoid.followerid and user.user_id, using CREATE INDEX, and use LEFT JOIN clause on your queries instead:
SELECT *
FROM user u
LEFT JOIN SELECT poster_id, COUNT(*) as count FROM post p GROUP BY poster_id
ON (u.user_id = p.poster_id)
ORDER BY count DESC;
and:
SELECT * FROM post AS p
LEFT JOIN (SELECT followerid FROM followtoid) AS f
ON (p.userid=f.followerid)
WHERE p.userid = {$_SESSION['userid']}
Use a JOIN for the first query
SELECT p.*
FROM post p
JOIN follow f ON p.post_id = f.followtoid
WHERE f.followerid = $_SESSION['userid']
and a JOIN plus a GROUP BY for the second
SELECT u.*, tbl.postCount
FROM user u
JOIN (
SELECT poster_id, COUNT(*) AS postCount
FROM post p
GROUP BY posterID
) tbl ON tbl.poster_id = u.id
ORDER BY postCount DESC
You can accomplish the second query without a subquery:
SELECT u.*, COUNT(p.poster_id) as postCount
FROM user u
LEFT JOIN post p
ON (u.user_id = p.poster_id)
GROUP BY u.user_id
ORDER BY postCount DESC;

mysql select multitable - join

say i had the following tables
user_table
id username
1 abc
2 def
3 ghij
courses_table
id title
1 csc
2 math
3 syn
user_courses
user_id course_id
2 1
1 3
2 3
i want to select the username whos taking course 1 AND 3 ,
not at least 1 or 3 , i mean both 1 and 3
i've tried the following mysql queries
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id = 1 AND uc.course_id=3;
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id IN (1,3);
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id IN (1,3) AND uc.user_id = u.id ;
the first and third queries executed with no results shown , and the second one show all users who had at least course_id 1 or 3
if you are wondering why am i using the LEFT JOIN , this is because i need to join table's results , and the above line of code is just an example , and im using to get data from about 9 tables using the LEFT join .
any help please ? thanks
SELECT DISTINCT u.* FROM user_table as u LEFT JOIN user_courses as uc ON uc.user_id = u.id WHERE uc.course_id IN( 1,3) AND uc.user_id = 2 ";
this show me the result i want , its output "def" ,
but i can't use the user_id as a static value ( number 2 in this example )
This problem is called Relational Division
SELECT a.id, a.username
FROM user_table a
INNER JOIN user_courses b
ON a.id = b.user_ID
WHERE b.course_ID IN (1,3)
GROUP BY a.id, a.username
HAVING COUNT(*) = 2
SQL of Relational Division
If course_ID is not unique for every users considering that the user have retake the course, a DISTINCT keyword is needed to coung unique courses,
SELECT a.id, a.username
FROM user_table a
INNER JOIN user_courses b
ON a.id = b.user_ID
WHERE b.course_ID IN (1,3)
GROUP BY a.id, a.username
HAVING COUNT(DISTINCT b.course_ID) = 2
SQLFiddle Demo
OUTPUT
╔════╦══════════╗
║ ID ║ USERNAME ║
╠════╬══════════╣
║ 2 ║ def ║
╚════╩══════════╝
please try this:
SELECT
U.id,
U.username
FROM
user_courses UC
INNER JOIN user_table U
ON UC.`user_id` = U.`id`
WHERE UC.`course_id` = 1
OR UC.`course_id` = 3
GROUP BY U.`id`
HAVING COUNT(*) > 1

Counting rows from second table

I have two tables in mysql database
groups
id|name
_______
1 |red
2 |blue
3 |green
4 |white
and users
id|name |group
_______________
1 |joe |1
2 |max |1
3 |anna |2
4 |lisa |2
So... joe and max are in the "red" group, anna and lisa are in the "blue" group.
How can I make simple listing of groups which would contain the number of
persons in that group
For example
red - 2
blue - 2
green - 0
white - 0
Most the other answers are basically correct, but forgot an important detail: GROUP is a reserved word in SQL, so your column name must be escaped:
SELECT groups.name, COUNT(*) AS total_members
FROM groups
LEFT OUTER JOIN users
ON users.`group` = groups.id
GROUP BY groups.id
check if this works....
SELECT COUNT(*), groups.name FROM groups, users WHERE users.group=groups.id GROUP BY groups.name
UPDATE
SELECT groups.name, COUNT(users.*) FROM groups LEFT JOIN users
ON groups.id=users.group GROUP BY groups.name
this will keep the colors even if they dont have any name related
Give this a try:
select g.name, count(u.id) from groups g
left join users u on g.id = u.group
group by g.id, g.name
Try this
SELECT COUNT(g.id) as count, g.name
FROM groups as g
LEFT JOIN users as u
ON u.group = g.id
GROUP BY g.id
This should work
SELECT g.*, COUNT(DISTINCT u.id) FROM `groups` g
INNER JOIN `users` u on g.id = u.group
GROUP BY u.id
maybe this should work
SELECT g.name, COUNT( u.id ) AS Totoal
FROM `groups` g
INNER JOIN `users` u ON g.id = u.group
GROUP BY g.id

Categories