Table name alias scope in sub-select query - php

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

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.

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

how to use INNER JOIN and IN Clause in same query

i have three tables and want to run INNER JOIN and IN clause on them.
can anyone tell me where i am doing wrong
SELECT `tblinvoices`.id,`tblinvoices`.userid,`firstname`,`lastname`
FROM `tblinvoices`
WHERE `paymentmethod`IN
(SELECT `gateway` FROM `tblpaymentgateways` WHERE `setting`='type' AND `value` = 'CC')
INNER JOIN `tblclients` ON `tblinvoices`.userid=`tblclients`.id"
JOIN comes before WHERE:
SELECT tblinvoices.id,
tblinvoices.userid,
firstname,
lastname
FROM
tblinvoices
INNER JOIN tblclients
ON tblinvoices.userid = tblclients.id
WHERE
paymentmethod IN
(select gateway
FROM tblpaymentgateways
WHERE setting='type'
AND value = 'CC')

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

mysql request from two tables when one is empty

I have two tables. And my request return me zero rows if my second table is empty and first - isn't... How can I solve this problem?
Table: users
id username name email
1 myuname myname myemail#domain.com
Table: accounts
customerid phone params
1 +1111 NULL
My sql request is below:
SELECT
A.phone,
A.params,
U.email,
U.username,
U.name
FROM `account` A, `users` U
WHERE A.customerid = U.id LIMIT 1';
The request above return zero rows if my account table is empty and users table isn't...
How can I solve this problem?
Thanks.
You can use a LEFT JOIN:
SELECT
A.phone,
A.params,
U.email,
U.username,
U.name
FROM
`account` A LEFT JOIN `users` U ON A.customerid = U.id
LIMIT 1
A LEFT JOIN will select all rows from the first table and only the rows on the second table that matches. If there is no match, U.email, U.username and U.name will be NULL.
You need to LEFT JOIN your tables.
'account' a LEFT JOIN 'users' u ON u.id = a.customerid
Try this
SELECT
A.phone,
A.params,
U.email,
U.username,
U.name
FROM account a
LEFT JOIN users as u ON u.id = a.customerid;

Categories