php mysql use subquery result in WHERE clause in the same query - php

is it possible to use a subquery result as a criteria in WHERE clause in the same query. i have this sql code. i want to compare the ASSESSEDINCLASS which is a result in the subquery and C.SLOTS to determine it the slot is full or not. is this even possible in a single query? thanks in advance
$str = "SELECT
c.id,
c.code AS classcode,
section.name AS sectionname,
subject.code,
subject.subdesc,
c.units,
sched.name AS schedule,
c.slots,
c.dissolved,
c.tutorial,
c.inst,
instructor.lname,
instructor.fname,
instructor.mname,
instructor.suffix,
(SELECT
Count(e.enrollno)
FROM
enrolldet AS e
Inner Join enroll ON e.enrollno = enroll.enrollno
Inner Join class ON e.class = class.id
WHERE
enroll.validated = '1' AND
class.id = c.id) as validatedinclass,
(SELECT
Count(e.enrollno)
FROM
enrolldet AS e
Inner Join enroll ON e.enrollno = enroll.enrollno
Inner Join class ON e.class = class.id
WHERE
enroll.assessed = '1' AND
class.id = c.id) as assessedinclass,
(SELECT
q.id
FROM
merged
Inner Join class AS q ON merged.mothercode = q.id
WHERE
merged.mergefrom = c.id) AS mergedto_mothercode
FROM
class AS c
Left Join sched ON c.sched = sched.id
Left Join section ON c.section = section.id
Left Join subject ON c.subject = subject.id
Left Join instructor ON c.inst = instructor.userid
Left Join course ON section.course = course.id
Inner Join period ON c.period = period.id
WHERE
(period.id = '".$period."' OR period.code = '".$period."')";
if($status == 'open'){
$str .= " AND c.slots < assessedinclass";
}
$str .= " ORDER BY subject.subdesc";

To answer your question yes you could by using Having clause, Make you use it after where clause
having assessedinclass = someval
Or
$str .= " HAVING c.slots < assessedinclass";
But what i prefer don't use dependent sub queries instead use join for these as sub clause to your main query somewhat like below
SELECT ....,
COALESCE(aic.assessedinclass, 0) AS assessedinclass,
FROM class AS c
JOINS....
LEFT JOIN (SELECT class.id,
COUNT(e.enrollno) AS assessedinclass
FROM enrolldet AS e
INNER JOIN enroll
ON e.enrollno = enroll.enrollno
INNER JOIN class
ON e.class = class.id
WHERE enroll.assessed = '1'
GROUP BY class.id) aic
ON aic.id = c.id
WHERE ( period.id = '".$period."' OR period.code = '".$period."' )
AND c.slots < COALESCE(aic.assessedinclass, 0)

Related

mySql LEFT JOIN not returning data as expected when Condition by ID php variable

When I use the PHP $qs variable in the WHERE condition it works fine but in LEFT JOIN condition, it's not returning any data.
Problem Line: AND e.terms_id_user =
My Query: (Working)
SELECT
*,
'users_staff_driving_license' AS driving_license_link,
DATE_FORMAT(terms_date_created,'%a %d-%M-%Y %r') AS udate_created,
DATE_FORMAT(terms_date_updated,'%a %d-%M-%Y %r') AS udate_updated
FROM users AS a
LEFT JOIN users_staff_details AS b
ON a.user_id = b.users_staff_id_user
LEFT JOIN user_access AS c
ON a.user_id_access_level = c.user_access_id
LEFT JOIN businesses AS d
ON a.user_id_client = d.business_id
LEFT JOIN terms AS e
ON e.terms_id_client = 'AA0000001'
AND e.terms_id_store = '1'
AND e.terms_id_user = 1001
AND e.terms_datatype = 'users_staff_driving_license'
WHERE
a.user_id = '$qs'
My Query: (Not Working)
SELECT
*,
'users_staff_driving_license' AS driving_license_link,
DATE_FORMAT(terms_date_created,'%a %d-%M-%Y %r') AS udate_created,
DATE_FORMAT(terms_date_updated,'%a %d-%M-%Y %r') AS udate_updated
FROM users AS a
LEFT JOIN users_staff_details AS b
ON a.user_id = b.users_staff_id_user
LEFT JOIN user_access AS c
ON a.user_id_access_level = c.user_access_id
LEFT JOIN businesses AS d
ON a.user_id_client = d.business_id
LEFT JOIN terms AS e
ON e.terms_id_client = 'AA0000001'
AND e.terms_id_store = '1'
AND e.terms_id_user = '$qs'
AND e.terms_datatype = 'users_staff_driving_license'
WHERE
a.user_id = '$qs'

PHP, Mysql sub query with where clause

I have a query that display all my CLASS details, now I want a sub query that will count all enrolled student in that class.
I tried using two separate query and trying to merge them but I'm not successful doing so.
This is my query so far:
$str = "SELECT
class.id,
class.code AS classcode,
section.name AS sectionname,
subject.code,
class.units,
sched.name AS schedule,
class.slots,
class.dissolved,
(SELECT
Count(enrolldet.enrollno)
FROM
enrolldet
Inner Join enroll ON enrolldet.enrollno = enroll.enrollno
Inner Join class ON enrolldet.class = class.id
WHERE
enroll.validated = '1' AND
class.id = class.id) AS enrolled
FROM
class
Left Join sched ON class.sched = sched.id
Left Join section ON class.section = section.id
Left Join subject ON class.subject = subject.id
";
You don't need all those joins in the subquery. This should suffice:
(SELECT Count(*)
FROM enrolldet ed JOIN
enroll e
ON ed.enrollno = e.enrollno
WHERE e.validated = 1 AND
ed.class = c.id
) AS enrolled
That is, you don't need class in the subquery. And, I'm guessing that validated is a number so I removed the single quotes around "1".
You can't have the class table of both the main query and the subquery named class, because the subquery has access to both tables and this results in the SQL engine being confused due to the ambiguity.
To fix your query, give an alias, like cls, the inner one and change the AND clause to:
AND `class`.`id` = `cls`.`id`
Also, note that your subquery can be simplified by removing the inner class table altogether, since the subquery can access the class table of the main query, as already mentioned.
Code:
SELECT
`class`.`id`,
`class`.`code` AS `classcode`,
`section`.`name` AS `sectionname`,
`subject`.`code`,
`class`.`units`,
`sched`.`name` AS `schedule`,
`class`.`slots`,
`class`.`dissolved`,
(
SELECT COUNT(`enrollno`)
FROM `enrolldet`
INNER JOIN `enroll`
ON `enrolldet`.`enrollno` = `enroll`.`enrollno`
WHERE `enroll`.`validated` = '1'
AND `enrolldet`.`class` = `class`.`id`
) AS `enrolled`
FROM `class`
LEFT JOIN `sched` ON `class`.`sched` = `sched`.`id`
LEFT JOIN `section` ON `class`.`section` = `section`.`id`
LEFT JOIN `subject` ON `class`.`subject` = `subject`.`id`
$str = "SELECT
c.id,
c.code AS classcode,
section.name AS sectionname,
subject.code,
c.units,
sched.name AS schedule,
c.slots,
c.dissolved,
(SELECT
Count(e.enrollno)
FROM
enrolldet AS e
Inner Join enroll ON e.enrollno = enroll.enrollno
Inner Join class ON e.class = class.id
WHERE
enroll.validated = '1' AND
class.id = c.id) as enrolled
FROM
class AS c
Left Join sched ON c.sched = sched.id
Left Join section ON c.section = section.id
Left Join subject ON c.subject = subject.id";
i got the correct answer using this. for future reference. i just added aliases for each table

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

insert php code in sql query

function search_num_rows($param){
$company_name=$param['company_name'];
$loan_no=$param['loan_no'];
$q = $this->db->query("select Count(0) as num_rows
from contact_new
inner join companies c on contact_new.company_id = c.id
inner join history on contact_new.id = history.receiver_email
inner join escalation_level on contact_new.escalation_level_id = escalation_level.id
inner join departments on contact_new.departmend_id = departments.id
WHERE loan_no= '$loan_no' if($company_name){ AND company_name= '$company_name'} ")->result();
return $q[0]->num_rows;
}
can i insert the php code as i done in where clause.Is there any other way to do this without using active records.
It's actually very easy:
function search_num_rows($param){
$company_name = (isset($param['company_name']) && !empty($param['company_name']) ? " AND company_name = '$param[company_name]'" : '');
$loan_no=$param['loan_no'];
$q = $this->db->query("select Count(0) as num_rows
from contact_new
inner join companies c on contact_new.company_id = c.id
inner join history on contact_new.id = history.receiver_email
inner join escalation_level on contact_new.escalation_level_id = escalation_level.id
inner join departments on contact_new.departmend_id = departments.id
WHERE loan_no= '$loan_no' $company_name")->result();
return $q[0]->num_rows;
}

Categories