Display all clients who have booked a room - php

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

Related

I'm not able to convert the Mysql query into laravel query builder

I'm struggling to convert this below MySQL query into laravel query builder. It has a lot of joins and subqueries inside. Can someone please help me?
MYSQL query:
SELECT a.id , b.*, a.agent_id, td.contacts, td.addresses
FROM teams a
left join team_details as td on td.team_id = a.id
LEFT OUTER JOIN
(
SELECT m.id, m.due_date, t.team_id, m.department, m.assigned_to , cm.title, u.name
FROM (
SELECT team_id, MAX(due_date) AS due_date
FROM campaign_activities where task_status=false and due_date is not null
GROUP BY team_id
) t JOIN campaign_activities m ON m.team_id = t.team_id AND t.due_date = m.due_date
left join campaign_activity_masters cm on cm.id = m.camp_activity_id
left join users u on u.id = m.assigned_to
) b ON a.id = b.team_id
order by a.id
I'm trying something like below but got stuck with LEFT OUTER JOIN as it has sub query inside :).
DB::table('teams as a')
->leftjoin('team_details as td', 'td.team_id','=','a.id')
->select('a.id', 'b.*', 'a.agent_id','td.contacts','td.addresses')
->leftouterjoin(DB::select(DB::raw('SELECT m.id, m.due_date, t.team_id, m.department, m.assigned_to , cm.title, u.name
FROM (
SELECT team_id, MAX(due_date) AS due_date
FROM campaign_activities where task_status=false and due_date is not null
GROUP BY team_id
) t JOIN campaign_activities m ON m.team_id = t.team_id AND t.due_date = m.due_date
left join campaign_activity_masters cm on cm.id = m.camp_activity_id
left join users u on u.id = m.assigned_to')))
->get();
Any suggestions, please? I want to apply paginate function paginate() instead of get() for this query builder.
I think you should try.
$cards = DB::select("SELECT a.id , b.*, a.agent_id, td.contacts, td.addresses
FROM teams a
left join team_details as td on td.team_id = a.id
LEFT OUTER JOIN
(
SELECT m.id, m.due_date, t.team_id, m.department, m.assigned_to , cm.title, u.name
FROM (
SELECT team_id, MAX(due_date) AS due_date
FROM campaign_activities where task_status=false and due_date is not null
GROUP BY team_id
) t JOIN campaign_activities m ON m.team_id = t.team_id AND t.due_date = m.due_date
left join campaign_activity_masters cm on cm.id = m.camp_activity_id
left join users u on u.id = m.assigned_to
) b ON a.id = b.team_id
order by a.id");
Hope it help you.

JOIN query not producing the correct results

I have the following query where I am trying to join my profile_img and users table to match the id's in the friends table (friend_one or friend_two) in oder to get their profile image or user information.
As of now, I do not get any errors...just not the correct results I am looking for. There should be two results that show relation to :profile_user... 5 and 2, which would also give ocean and lake for their profile_img.
The parameter :profile_user is equal to 1. :total_status = 2.
I am not sure if my ON clauses are throwing this off or not. I am not sure how to make u.id = to both the friend_one or friend_two.
Does anyone see why this isn't working?
Here is a fiddle
SELECT f.*, u.*, p.*, IFNULL(p.img, 'profile_images/default.jpg') AS img
FROM friends f
JOIN
users u
ON u.id = (f.friend_one or f.friend_two)
LEFT JOIN
profile_img p
ON p.user_id = f.friend_one or f.friend_two and p.id = (select max(p2.id) from profile_img p2 where p2.user_id = p.user_id)
WHERE (friend_one = :profile_user or friend_two = :profile_user)
AND status = :total_status
Full code, which is showing 0 results.
$friend_status = 2;
$friend_sql = "
SELECT f.*, u.*, p.*, IFNULL(p.img, 'profile_images/default.jpg') AS img
FROM friends f
JOIN
users u
ON u.id = (f.friend_one or f.friend_two)
LEFT JOIN
profile_img p
ON p.user_id = f.friend_one or f.friend_two and p.id = (select max(p2.id) from profile_img p2 where p2.user_id = p.user_id)
WHERE (friend_one = :profile_user or friend_two = :profile_user)
AND status = :total_status
";
$friend_stmt = $con->prepare($friend_sql);
$friend_stmt->execute(array(':profile_user' => $profile_user, ':total_status' => $friend_status));
$friend_total_rows = $friend_stmt->fetchAll(PDO::FETCH_ASSOC);
$count_total_friend = $friend_stmt->rowCount();
?>
<div id="friend-list-container">
<div id="friend-list-count">Friends <span class="light-gray"><?php echo $count_total_friend; ?></span></div>
<div id="friend-list-image-container">
<?php
foreach ($friend_total_rows as $friend_total_row) {
$friend_1 = $friend_total_row['friend_one'];
$friend_2 = $friend_total_row['friend_two'];
$friend_img = $friend_total_row['img'];
$friend_username = $friend_total_row['username'];
if($friend_1 !== $profile_user) {
echo $friend_1;
echo $friend_img;
echo $friend_username;
}
if($friend_2 !== $profile_user) {
echo $friend_2;
echo $friend_img;
echo $friend_username;
}
}
after I posted the below I realized mysql does not support cte -- here a version without:
SELECT f.*,
u1.*,
u2.*,
p1.*,
p2.*,
IFNULL(p1.img, 'profile_images/default.jpg') AS img1,
IFNULL(p2.img, 'profile_images/default.jpg') AS img2
FROM friends f
LEFT JOIN users u1 ON u1.id = f.friend_one
LEFT JOIN users u2 ON u2.id = f.friend_two
LEFT JOIN (
SELECT user_id, max(id) as mid
FROM profile_img
GROUP BY user_id
) max1 ON u1.user_id = max1.user_id
LEFT JOIN (
SELECT user_id, max(id) as mid
FROM profile_img
GROUP BY user_id
) max2 ON u2.user_id = max2.user_id
LEFT JOIN profile_img p1 ON p1.user_id = f.friend_one and p1.id = max1.mid
LEFT JOIN profile_img p2 ON p2.user_id = f.friend_two and p2.id = max2.mid
WHERE (friend_one = :profile_user or friend_two = :profile_user)
AND status = :total_status
WITH maxImage AS
(
SELECT user_id, max(id) as mid
FROM profile_img
GROUP BY user_id
)
SELECT f.*,
u1.*,
u2.*,
p1.*,
p2.*,
IFNULL(p1.img, 'profile_images/default.jpg') AS img1,
IFNULL(p2.img, 'profile_images/default.jpg') AS img2
FROM friends f
LEFT JOIN users u1 ON u1.id = f.friend_one
LEFT JOIN users u2 ON u2.id = f.friend_two
LEFT JOIN maxImage max1 ON u1.user_id = max1.user_id
LEFT JOIN maxImage max2 ON u2.user_id = max2.user_id
LEFT JOIN profile_img p1 ON p1.user_id = f.friend_one and p1.id = max1.mid
LEFT JOIN profile_img p2 ON p2.user_id = f.friend_two and p2.id = max2.mid
WHERE (friend_one = :profile_user or friend_two = :profile_user)
AND status = :total_status
If you have an "id" column in your friend table that is the same as the column "id" of your user table, i think you should try this
ON u.id = f.id
instead of
ON u.id = (f.friend_one or f.friend_two)
Based on the data in the mentioned SQL Fiddle. Below is the query that i think will help
select
res1.firstname as FriendOneFirstName,
res1.lastname as FriendOneLastName,
res1.img as FriendOneImage,
user1.firstname as FriendTwoFirstName,
user1.lastname as FriendTwoLastName,
pf1.img as FirendTwoProfileImage
from
(select usr.id,usr.firstname,usr.lastname,pf.img,frds.friend_two
from users usr
inner join friends frds on usr.id=frds.friend_one
inner join profile_img pf on usr.id = pf.user_id
) as res1
inner join users user1 on user1.id=res1.friend_two
inner join profile_img pf1 on user1.id=pf1.user_id
order by user1.id;

How can I combine 2 complex mysql queries

So I have two MySQL queries that if I had the knowledge to combine I would but I don't so that's why I turned to "SO", and in that case I haven't tried anything because its out of my scope. I want to combine all in one query and if that's not possible please let me know.
Query one "This selects all of your friends posts including yours":
"SELECT b.*, c.photo, d.name, e.status
FROM post b
INNER JOIN profile c
INNER JOIN user d
INNER JOIN user_friendship e
ON b.from_user = c.user_id
AND b.from_user = d.id
AND e.friend_id = b.from_user
WHERE e.status = :status
AND e.user_id = :id
ORDER BY b.id DESC LIMIT 20"
Query two "This selects all of the people your following posts":
"SELECT b.*, c.photo, d.name, e.status
FROM post b
INNER JOIN profile c
INNER JOIN user d
INNER JOIN user_follower e
ON b.from_user = c.user_id
AND b.from_user = d.id
AND e.to_id = b.from_user
WHERE e.status = :status
AND e.who_id = :id
ORDER BY b.id DESC LIMIT 20"
I have combined these but with php alone. I'd like to combine both in one single MySQL query. Thanks in advance
SELECT *
FROM
(SELECT b.*,
c.photo,
d.name,
e.status
FROM post b
INNER JOIN profile c
INNER JOIN USER d
INNER JOIN user_friendship e ON b.from_user = c.user_id
AND b.from_user = d.id
AND e.friend_id = b.from_user
WHERE e.status = :status
AND e.user_id = :id LIMIT 20
UNION SELECT b.*,
c.photo,
d.name,
e.status
FROM post b
INNER JOIN profile c
INNER JOIN USER d
INNER JOIN user_follower e ON b.from_user = c.user_id
AND b.from_user = d.id
AND e.to_id = b.from_user
WHERE e.status = :status
AND e.who_id = :id LIMIT 20 ) MainQuery
ORDER BY id DESC
SELECT b.*, c.photo, d.name, e.status, "P"
FROM post b
INNER JOIN profile c
INNER JOIN user d
INNER JOIN user_friendship e
ON b.from_user = c.user_id
AND b.from_user = d.id
AND e.friend_id = b.from_user
WHERE e.status = :status
AND e.user_id = :id
ORDER BY b.id DESC LIMIT 20
UNION
SELECT b.*, c.photo, d.name, e.status, "F"
FROM post b
INNER JOIN profile c
INNER JOIN user d
INNER JOIN user_follower e
ON b.from_user = c.user_id
AND b.from_user = d.id
AND e.to_id = b.from_user
WHERE e.status = :status
AND e.who_id = :id
ORDER BY b.id DESC LIMIT 20
With the extra column you can see where the row is coming from (P = post, F = following)
Keep in mind that union will remove duplicate rows. If you want to see all rows use UNION ALL

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