how to use where condition in both parts of union in mysql - php

I'm using php and mysql for making a chat application.
I want to use a where condition in both parts of union but this not working
my code is :
$Query = "(SELECT u.userid, u.photo, u.username FROM `last_activity` AS la INNER JOIN user AS u ON la.userid = u.userid LEFT join private_chat pc ON u.userid = pc.sender_id WHERE la.last_activity_date BETWEEN '2020-09-21 10:20:00' AND '2020-09-21 10:30:00' AND u.username like '%amit%' ORDER BY pc.created_date DESC) UNION (SELECT userid, photo, username FROM user u LEFT join private_chat pc ON u.userid = pc.sender_id WHERE u.u_type = '2')";
and i want like and this not works
$Query = "(SELECT u.userid, u.photo, u.username FROM `last_activity` AS la INNER JOIN user AS u ON la.userid = u.userid LEFT join private_chat pc ON u.userid = pc.sender_id) UNION (SELECT userid, photo, username FROM user u LEFT join private_chat pc ON u.userid = pc.sender_id ) WHERE la.last_activity_date BETWEEN '2020-09-21 10:20:00' AND '2020-09-21 10:30:00' AND u.u_type = '2' AND u.username like '%amit%' ORDER BY pc.created_date DESC";

SELECT *
FROM
(
SELECT u.userid, u.photo, u.username, pc.created_date
FROM `last_activity` AS la
INNER JOIN `user` AS u ON la.userid = u.userid
LEFT JOIN private_chat pc ON u.userid = pc.sender_id
WHERE la.last_activity_date BETWEEN '2020-09-21 10:20:00' AND '2020-09-21 10:30:00'
AND u.username LIKE '%amit%'
UNION ALL
SELECT userid, photo, username, pc.created_date
FROM `user` u
LEFT JOIN private_chat pc ON u.userid = pc.sender_id
WHERE u.u_type = '2'
) a
ORDER BY a.created_date DESC;

Related

Display all clients who have booked a room

Subquery returns more than 1 row and this is the error. I want to print all the booked room details showing the client id and the owner id.
$query = "SELECT r.room_id, r.roomsize, r.numberroom, r.price, u.username,
(SELECT u.username FROM room_register r
INNER JOIN user_info u on r.owner_id = u.user_id
INNER JOIN booked b on b.room_id = r.room_id)as owner_name
FROM room_register r INNER JOIN booked b on b.room_id = r.room_id
INNER JOIN user_info u on u.user_id = b.booked_by";
You have too many joins in the subquery:
SELECT r.room_id, r.roomsize, r.numberroom, r.price, u.username,
(SELECT u.username
FROM user_info u
WHERE r.owner_id = u.user_id
) as owner_name
FROM room_register r INNER JOIN
booked b
ON b.room_id = r.room_id INNER JOIN
user_info u
ON u.user_id = b.booked_by;
Or just use two separate JOINs:
SELECT r.room_id, r.roomsize, r.numberroom, r.price, u.username,
uo.username as owner_name
FROM room_register r INNER JOIN
booked b
ON b.room_id = r.room_id INNER JOIN
user_info u
ON u.user_id = b.booked_by LEFT JOIN
user_info uo
ON uo.user_id = r.owner_id

Add a WHERE clause to a MySQL query

I have this MySQL query that works really well. What it's doing is displaying all the filenames (filename) in a database, along with the poster of that filename and then any user who is tagged with that filename (cp.user_id). Later on in the script I explode the tagGroup.
I have a created a new field in the tbl_collab table called 'approved' which can either be 'yes' or 'no' and I want to know how to add a WHERE clause to my query so only the users where approved="yes" in tbl_collab are displayed. How can I do this? Many thanks.
"SELECT up.id, up.file, up.title, p.user_name, p.user_id, GROUP_CONCAT(CONCAT(cp.user_id, '~', cp.user_name) SEPARATOR '|') AS tagGroup
FROM tbl_uploads up
LEFT JOIN tbl_users p ON up.user_id = p.user_id
LEFT JOIN tbl_collab c ON up.file = c.file
LEFT JOIN tbl_users cp ON cp.user_id = c.collab_userid
GROUP BY up.file ORDER BY up.id DESC LIMIT ? , ?"
This is how I am exploding the tagGroup.
$tag_array = explode('|' , $tagGroup);
foreach($tag_array as $tag) {
list($uid,$uname) = explode('~',$tag,2);
You can add this condition in where clause like
"SELECT up.id, up.file, up.title, p.user_name, p.user_id, GROUP_CONCAT(CONCAT(cp.user_id, '~', cp.user_name) SEPARATOR '|') AS tagGroup
FROM tbl_uploads up
LEFT JOIN tbl_users p ON up.user_id = p.user_id
LEFT JOIN tbl_collab c ON up.file = c.file
LEFT JOIN tbl_users cp ON cp.user_id = c.collab_userid
WHERE c.approved = 'yes'
GROUP BY up.file ORDER BY up.id DESC LIMIT ? , ?"
Or you can add this condition in joining condition like
"SELECT up.id, up.file, up.title, p.user_name, p.user_id, GROUP_CONCAT(CONCAT(cp.user_id, '~', cp.user_name) SEPARATOR '|') AS tagGroup
FROM tbl_uploads up
LEFT JOIN tbl_users p ON up.user_id = p.user_id
LEFT JOIN tbl_collab c ON up.file = c.file AND c.approved = 'yes'
LEFT JOIN tbl_users cp ON cp.user_id = c.collab_userid
GROUP BY up.file ORDER BY up.id DESC LIMIT ? , ?"
Add WHERE c.approved = 'yes'to your sql query ;) or change the JOIN-condition to LEFT JOIN tbl_collab c ON (up.file = c.file AND c.approved = 'yes')

Adding a JOIN to query resulting in a fail

I am trying to add my users table to my existing query so that I can match the users.id with the forum_topics.topic_creator, so I can match those and enable myself to assign that with that users username.
This is my original query.
$query2 = mysqli_query($con,"SELECT t.*, COUNT(p.topic_id)
AS tid2 FROM forum_topics AS t JOIN forum_posts
AS p on t.id = p.topic_id WHERE t.category_id = ".$cid."
GROUP BY t.id DESC")
I then tried doing this..
$query2 =mysqli_query($con,"SELECT t.*, COUNT(p.topic_id)
AS tid2 FROM forum_topics AS t JOIN forum_posts
AS p on t.id = p.topic_id WHERE t.category_id = ".$cid."
INNER JOIN users AS u
ON t.topic_creator = u.id
GROUP BY t.id DESC")
or die ("Query2 failed: %s\n".($query2->error));
I am getting the fail message.
What am I doing wrong?
WHERE clause should come after join:
SELECT t.*, COUNT(p.topic_id) AS tid2
FROM forum_topics AS t JOIN
forum_posts AS p on t.id = p.topic_id INNER JOIN
users AS u ON t.topic_creator = u.id
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC
EDIT:
To select the username as well:
SELECT t.*,u.username, COUNT(p.topic_id) AS tid2
FROM forum_topics AS t JOIN
forum_posts AS p on t.id = p.topic_id INNER JOIN
users AS u ON t.topic_creator = u.id
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC
The WHERE clause has to be placed after the INNER JOIN.
$query2 =mysqli_query($con,"SELECT t.*, COUNT(p.topic_id)
AS tid2 FROM forum_topics AS t
JOIN forum_posts AS p ON t.id = p.topic_id
INNER JOIN users AS u ON t.topic_creator = u.id
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC")
or die ("Query2 failed: %s\n".($query2->error));
Try this
SELECT t.*, COUNT(p.topic_id) AS tid2
FROM forum_topics t
JOIN forum_posts p ON (t.id = p.topic_id )
INNER JOIN users u ON (t.topic_creator = u.id)
WHERE t.category_id = ".$cid."
GROUP BY t.id DESC`

How do I embed a select in a select or call another function from a select?

I have a select statement like this:
SELECT c.id AS courseid, u.id AS userid
FROM
mdl_user_enrolments ue
join mdl_enrol e on e.id = ue.enrolid
join mdl_user u on u.id = ue.userid
join mdl_course c on c.id = e.courseid
I have another piece of data I want that does not have a direct relationship with the current tables. I have been calling this function in the output loop,
function getLastCourseAccessByUser($courseid, $userid){
global $DB;
return
$DB->get_record_sql('
SELECT FROM_UNIXTIME(time, "%m/%d/%Y") as ftime
FROM mdl_log
WHERE course = '.$courseid.' AND userid = '.$userid.'
ORDER BY time DESC
limit 1
');
}
but would rather get all the data once, and not call back the db.
I am trying this:
SELECT c.id AS courseid, u.id as userid
(
SELECT FROM_UNIXTIME(time, "%m/%d/%Y") as ftime
FROM mdl_log
WHERE course = c.id AND userid = u.id
) AS lastaccessdate
FROM
mdl_user_enrolments ue
join mdl_enrol e on e.id = ue.enrolid
join mdl_user u on u.id = ue.userid
join mdl_course c on c.id = e.courseid
Or, could I call the function directly from the sql like this:
SELECT c.id AS courseid, u.id as userid,
'.getLastCourseAccessByUser(c.id,u.id).' AS lastaccessdate
FROM
mdl_user_enrolments ue
join mdl_enrol e on e.id = ue.enrolid
join mdl_user u on u.id = ue.userid
join mdl_course c on c.id = e.courseid
Thank you.
SELECT c.id AS courseid, u.id AS userid, FROM_UNIXTIME(t.time, "%m/%d/%Y") as ftime
FROM
mdl_user_enrolments ue
join mdl_enrol e on e.id = ue.enrolid
join mdl_user u on u.id = ue.userid
join mdl_course c on c.id = e.courseid
join mdl_log t on t.course = c.id and t.userid = u.id
You can put AND and OR clauses in a join in mysql so you can join on both your conditionals. Though you may want to make it an outer join so that it won't fail the entire query if the conditionals aren't met
Otherwise your sub select option should also work (this one)
SELECT c.id AS courseid, u.id as userid
(
SELECT FROM_UNIXTIME(time, "%m/%d/%Y") as ftime
FROM mdl_log
WHERE course = c.id AND userid = u.id
) AS lastaccessdate
FROM
mdl_user_enrolments ue
join mdl_enrol e on e.id = ue.enrolid
join mdl_user u on u.id = ue.userid
join mdl_course c on c.id = e.courseid
The more data you process on the MySQL Server side, the less traffic is generated between the MySQL Server and your PHP application, thus speeding up the application. I would say to get all the data from the server at once and not go back and forth too many times.
You can also create the getLastCourseAccessByUser function as a stored function in MySQL if you need to re-use it in other applications:
DELIMITER \\
DROP FUNCTION IF EXISTS getLastCourseAccessByUser\\
CREATE FUNCTION getLastCourseAccessByUser (in_course_id INT, in_user_id VARCHAR(50)
RETURNS STRING
BEGIN
SELECT FROM_UNIXTIME(time, "%m/%d/%Y") AS ftime
FROM mdl_log
WHERE course = in_course_id AND userid = in_user_id
ORDER BY time DESC
LIMIT 1
END\\
DELIMITER ;
Then you could use it in your SELECT statement:
SELECT c.id AS courseid,
u.id as userid,
getLastCourseAccessByUser(c.id,u.id) AS lastaccessdate
FROM mdl_user_enrolments ue
JOIN mdl_enrol e on e.id = ue.enrolid
JOIN mdl_user u on u.id = ue.userid
JOIN mdl_course c on c.id = e.courseid

Table name alias scope in sub-select query

Please have a look at the query below - I am getting Unknown column 'u.id' in 'on clause'
SELECT id, username,
coalesce(
(SELECT name from company c
INNER JOIN user_company uc
ON uc.user_id = u.id
AND c.id = uc.company_id), 'NOT-AVAILABLE'
) companyname
FROM `user` u
Based on your comment, the correlation can't be placed within the JOIN of the correlated sub-query.
It can, however, be placed in the WHERE clause of the correlated sub-query.
SELECT
id,
username,
coalesce(
(SELECT name
FROM company c
INNER JOIN user_company uc
ON c.id = uc.company_id
WHERE uc.user_id = u.id
),
'NOT-AVAILABLE'
) companyname
FROM
`user` u
That answers your explicit question; why your query failed syntactically.
I would, however, replace the whole correlation with a simple LEFT JOIN.
SELECT
u.id,
u.username,
COALESCE(c.name, 'NOT-AVAILABLE') companyname
FROM
`user` u
LEFT JOIN
`user_company` uc
ON uc.user_id = u.id
LEFT JOIN
`company` c
ON c.id = uc.company_id
One way to fix it:
SELECT u.id,
u.username,
COALESCE(aux.name, 'NOT-AVAILABLE') as 'companyname'
FROM `user` u
LEFT JOIN
(SELECT user_id, name from company c
INNER JOIN user_company uc
ON c.id = uc.company_id) aux ON aux.user_id = u.id
Another way to fix it:
SELECT u.id,
u.username,
COALESCE(c.name, 'NOT-AVAILABLE') AS 'companyname'
FROM `user` u
LEFT JOIN user_company uc ON uc.user_id = u.id
LEFT JOIN company c ON c.id = uc.company_id

Categories