i have a query and i want to filter the result set using an ALIASED column in my WHERE condition, ive read that you cannnot do it but i dont have yet an alternative way to do it efficiently since im working on thousands of records.
$str = "SELECT
mainclass.id AS classid,
mainclass.code AS classcode,
Sum(CASE WHEN enroll.acctok = '1' AND enroll.assessed = '1'
THEN enroll.assessed
ELSE 0 end) AS assessedinclass,
Sum(enroll.validated = '1') AS validatedinclass,
section.name AS sectionname,
subject.code AS subcode,
subject.subdesc,
mainclass.units,
sched.name AS schedule,
mainclass.tutorial,
mainclass.dissolved,
mainclass.slots,
mainclass.ismother,
mergeclass.code AS mothercode,
mergeclass.id AS mothercodeid,
mergeclass.slots AS mothercodeslots,
mainclass.mergein,
mainclass.inst,
instructor.lname,
instructor.fname,
instructor.mname,
instructor.suffix
FROM
class AS mainclass
Left Join enrolldet ON mainclass.id = enrolldet.class
Left Join enroll ON enrolldet.enrollno = enroll.enrollno
Inner Join period ON mainclass.period = period.id
Inner Join section ON mainclass.section = section.id
Inner Join subject ON mainclass.subject = subject.id
Left Join sched ON mainclass.sched = sched.id
Left Join class AS mergeclass ON mainclass.mergein = mergeclass.id
Left Join instructor ON mainclass.inst = instructor.userid
Left Join course ON section.course = course.id
WHERE
(period.id = :period OR period.code = :period)";
if($level != ''){
$str .= " AND course.level = '".$level."'";
}
if($dept != ''){
$str .= " AND course.dept = '".$dept."'";
}
if($display != ''){
switch ($display) {
case 'open':
$str .= " AND mainclass.slots > assessedinclass";
break;
case 'dissolved':
$str .= " AND mainclass.dissolved = 1";
break;
case 'tutorial':
$str .= " AND mainclass.tutorial = 1";
break;
case 'closed':
$str .= " AND mainclass.slots <= assessedinclass";
break;
}
}
$str .= "GROUP BY
mainclass.id,
mainclass.code";
$str .= " ORDER BY subject.code, mainclass.id";
return $this->_db->select($str,array(':period' => $period));
im trying to filter it using the ASSESSEDINCLASS WHERE mainclass.slots > ASSESSEDINCLASS means the subject is OPEN
while if mainclass.slots <= ASSESSEDINCLASS it will be considered CLOSED
You can try below. Write an outer select which will have all the required columns for you to process filters.
select
classid,
classcode,
assessedinclass,
validatedinclass,
sectionname,
subcode,
subdesc,
units,
schedule,
tutorial,
dissolved,
slots,
ismother,
mothercode,
mothercodeid,
mothercodeslots,
mergein,
inst,
lname,
fname,
mname,
suffix
from
(select
mainclass.id AS classid,
mainclass.code AS classcode,
Sum(case when enroll.acctok = '1' and enroll.assessed = '1'
then enroll.assessed
else 0
end) as assessedinclass,
Sum(enroll.validated = '1') AS validatedinclass,
section.name AS sectionname,
subject.code AS subcode,
subject.subdesc,
mainclass.units,
sched.name AS schedule,
mainclass.tutorial,
mainclass.dissolved,
mainclass.slots,
mainclass.ismother,
mergeclass.code AS mothercode,
mergeclass.id AS mothercodeid,
mergeclass.slots AS mothercodeslots,
mainclass.mergein,
mainclass.inst,
instructor.lname,
instructor.fname,
instructor.mname,
instructor.suffix
from
class as mainclass
left join
enrolldet on mainclass.id = enrolldet.class
left join
enroll on enrolldet.enrollno = enroll.enrollno
inner join
period on mainclass.period = period.id
inner join
section on mainclass.section = section.id
inner join
subject on mainclass.subject = subject.id
left join
sched on mainclass.sched = sched.id
left join
class as mergeclass on mainclass.mergein = mergeclass.id
left join
instructor on mainclass.inst = instructor.userid
left join
course on section.course = course.id)
where
(period.id = :period OR period.code = :period);
Your final query would be -
select
<req_cols>
from
(select
<agg_cols>
from
table
group by
<grpCols>)
where
<filter on agg cols>
$str = "SELECT
mainclass.id AS classid,
mainclass.code AS classcode,
Sum(CASE WHEN enroll.acctok = '1' AND enroll.assessed = '1'
THEN enroll.assessed
ELSE 0 end) AS assessedinclass,
Sum(enroll.validated = '1') AS validatedinclass,
section.name AS sectionname,
subject.code AS subcode,
subject.subdesc,
mainclass.units,
sched.name AS schedule,
mainclass.tutorial,
mainclass.dissolved,
mainclass.slots,
mainclass.ismother,
mergeclass.code AS mothercode,
mergeclass.id AS mothercodeid,
mergeclass.slots AS mothercodeslots,
mainclass.mergein,
mainclass.inst,
instructor.lname,
instructor.fname,
instructor.mname,
instructor.suffix
FROM
class AS mainclass
Left Join enrolldet ON mainclass.id = enrolldet.class
Left Join enroll ON enrolldet.enrollno = enroll.enrollno
Inner Join period ON mainclass.period = period.id
Inner Join section ON mainclass.section = section.id
Inner Join subject ON mainclass.subject = subject.id
Left Join sched ON mainclass.sched = sched.id
Left Join class AS mergeclass ON mainclass.mergein = mergeclass.id
Left Join instructor ON mainclass.inst = instructor.userid
Left Join course ON section.course = course.id
WHERE
(period.id = :period OR period.code = :period)";
if($level != ''){
$str .= " AND course.level = '".$level."'";
}
if($dept != ''){
$str .= " AND course.dept = '".$dept."'";
}
if($display != ''){
switch ($display) {
case 'open':
$str .= " AND mainclass.slots > assessedinclass";
break;
case 'dissolved':
$str .= " AND mainclass.dissolved = 1";
break;
case 'tutorial':
$str .= " AND mainclass.tutorial = 1";
break;
case 'closed':
$str .= " AND mainclass.slots <= assessedinclass";
break;
}
}
$str .= "GROUP BY
mainclass.id,
mainclass.code";
$str .="HAVING <your condition>";
$str .= " ORDER BY subject.code, mainclass.id";
return $this->_db->select($str,array(':period' => $period));
Related
My code is constructing a web page where I display multiple tables of data based on a machine ID (machine_id). The end user wants to be able to scroll through all tables on a single page versus having a single page for each individual machine.
Attached is a screenshot of what the page looks like (actually displays more than just two tables on the page). Can I modify my code so that I'm not making multiple queries in the While loop as the machine_id changes?
$db = new Database();
$result = mysqli_query($conn, "SELECT machine_id, machine_name, display_order FROM machines WHERE active_board = 'YES' ORDER BY display_order ASC");
echo "<table>";
while ($row = mysqli_fetch_assoc($result)) {
$mach_id = $row["machine_id"];
$machine_name = $row["machine_name"];
$presspage = $row["machine_id"];
$machine_name = $row["machine_name"];
$daycount = '7';
$rows = $db -> select("SELECT a.machine_id, a.job_id, a.component, a.production_date, a.colors, a.hours, a.quantity, a.is_completed, a.artwork_image,
j.job_id, j.job_number, j.customer_id, j.job_name, j.total_cost, j.due_date, j.rework, j.pps, j.personalization, j.shipped, j.wave_csr,
c.customer_id, c.customer_name, c.board_color, c.text_color, u.full_name, p.component_name, d.delivery_method
FROM job_assignments a
LEFT JOIN jobs j ON a.job_id = j.job_id
LEFT JOIN customers c ON j.customer_id = c.customer_id
LEFT JOIN users u ON j.wave_csr = u.user_id
LEFT JOIN job_components p ON a.component = p.component_code
LEFT JOIN delivery_methods d ON j.method_id = d.method_id
WHERE a.machine_id = $presspage
ORDER BY j.job_number ASC");
echo "<tr>";
echo "<td>";
echo "<div id='dhtmlgoodies_dragDropContainer'>";
echo "<div id='dhtmlgoodies_mainContainer' align='center' vertical-align='middle'>";
echo "<h2>" . $machine_name . "</h2>";
for($x=0;$x<$daycount;$x++) {
$thehours = 0;
$theday = date('l M d', strtotime($date . " + {$x} day"));
$theday2 = date('Y-m-d', strtotime($date . " + {$x} day"));
$daycode = date('Md', strtotime($date . " + {$x} day"));
$totalhours = 0;
$pastdue_hours = 0;
$totalvalue = 0.00;
echo "<div style='width:180px; height:1500px; '>";
echo "<p>" . $theday . "</p>";
foreach ($rows as $row) {
$prod_date = $row["production_date"];
$shipped = $row["shipped"];
$hours = $row["hours"];
$value = $row["total_cost"];
$assignment_completed = 0;
$is_completed = $row["is_completed"];
if (($prod_date < date('Y-m-d')) AND ($shipped == 'NO') ) {
$prod_date = date('Y-m-d');
};
...
Screenshot example of web page.
You can join both the queries as
SELECT m.machine_id, m.machine_name, m.display_order, a.job_id, a.component, a.production_date, a.colors, a.hours, a.quantity, a.is_completed, a.artwork_image,
j.job_id, j.job_number, j.customer_id, j.job_name, j.total_cost, j.due_date, j.rework, j.pps, j.personalization, j.shipped, j.wave_csr,
c.customer_id, c.customer_name, c.board_color, c.text_color, u.full_name, p.component_name, d.delivery_method
FROM
machines m
LEFT JOIN job_assignments a USING (machine_id)
LEFT JOIN jobs j ON a.job_id = j.job_id
LEFT JOIN customers c ON j.customer_id = c.customer_id
LEFT JOIN users u ON j.wave_csr = u.user_id
LEFT JOIN job_components p ON a.component = p.component_code
LEFT JOIN delivery_methods d ON j.method_id = d.method_id
WHERE a.machine_id = $presspage and m.active_board = 'YES'
ORDER BY m.display_order, j.job_number;
You can first get all the machine ids from the first query into an array, then execute the second query for all machine ids in that array all at once. Below is a demonstrated example:
$db = new Database();
$result = mysqli_query($conn, "SELECT machine_id, machine_name, display_order FROM machines WHERE active_board = 'YES' ORDER BY display_order ASC");
$active_board_machine_ids = array();
while ($row = mysqli_fetch_assoc($result)) {
$active_board_machine_ids[] = $row["machine_id"];
}
$rows = $db -> select("SELECT a.machine_id, a.job_id, a.component, a.production_date, a.colors, a.hours, a.quantity, a.is_completed, a.artwork_image,
j.job_id, j.job_number, j.customer_id, j.job_name, j.total_cost, j.due_date, j.rework, j.pps, j.personalization, j.shipped, j.wave_csr,
c.customer_id, c.customer_name, c.board_color, c.text_color, u.full_name, p.component_name, d.delivery_method
FROM job_assignments a
LEFT JOIN jobs j ON a.job_id = j.job_id
LEFT JOIN customers c ON j.customer_id = c.customer_id
LEFT JOIN users u ON j.wave_csr = u.user_id
LEFT JOIN job_components p ON a.component = p.component_code
LEFT JOIN delivery_methods d ON j.method_id = d.method_id
WHERE a.machine_id IN ('".implode("','",$active_board_machine_ids)."')
ORDER BY j.job_number ASC");
I don't understand why following query is not return anything. If I change the query then it's return result.
what I'm doing now (No output)
$msg = array();
$getSearch = "SELECT contact_details . * , company.company_name, users.nickname FROM contact_details LEFT JOIN users ON users.user_id = contact_details.user_id LEFT JOIN company ON company.cid = contact_details.cid WHERE";
if(!empty($ad_company)){
$getSearch .= "company.company_name LIKE '$ad_company%' ";
}
$getSearch = mysql_query($getSearch);
while($searchResult = mysql_fetch_array($getSearch)){
$msg[] = $company = $searchResult['company_name'] . "<br/>";
}
echo json_encode($msg);
Change Code(Working)
$msg = array();
$getSearch = "SELECT contact_details . * , company.company_name, users.nickname FROM contact_details LEFT JOIN users ON users.user_id = contact_details.user_id LEFT JOIN company ON company.cid = contact_details.cid WHERE company.company_name LIKE '$ad_company%'";
//$msg[] = empty($ad_company) ? "empty company" : "not empty company"; //for checking and field has value
/*if(!empty($ad_company)){
$getSearch .= "company.company_name LIKE '$ad_company%' ";
}*/
$getSearch = mysql_query($getSearch);
while($searchResult = mysql_fetch_array($getSearch)){
$msg[] = $company = $searchResult['company_name'] . "<br/>";
}
echo json_encode($msg);
Maybe becouse you don't have a space between WHERE and company?
Try this
As answer by Mitja , you have missed the space between WHERE and company
$getSearch = "SELECT contact_details . * , company.company_name, users.nickname
FROM contact_details
LEFT JOIN users ON users.user_id = contact_details.user_id
LEFT JOIN company ON company.cid = contact_details.cid ";
if(!empty($ad_company)){
$getSearch .= " WHERE company.company_name LIKE '$ad_company%' ";
}
EDITED
$getSearch = "SELECT contact_details . * , company.company_name, users.nickname
FROM contact_details
LEFT JOIN users ON users.user_id = contact_details.user_id
LEFT JOIN company ON company.cid = contact_details.cid
WHERE 1=1 ";
if(!empty($ad_company)){
$getSearch .= " AND company.company_name LIKE '$ad_company%' ";
}
I have removed the WHERE from your $getSearch query and added to the one we are appending
$getSearch = "SELECT contact_details . * , company.company_name, users.nickname FROM contact_details LEFT JOIN users ON users.user_id = contact_details.user_id LEFT JOIN company ON company.cid = contact_details.cid";
if(!empty($ad_company)){
$getSearch .= " WHERE company.company_name LIKE '$ad_company%' ";
}
in future if you face problems like these always try to print only sql query before querying it with db.. this way you will get to see as if your query is correct or not
Can someone help me convert the following code to Yii query? I would liek it to return array of type models with derived column
$sql = 'UPDATE jobs
RIGHT JOIN (
SELECT jobs.JOBNO,
round(details' . $type['type'] . '.' . $type['km'] . ' * sum(PRICE),2) AS JOBSVALUE
FROM jobs
JOIN projects ON jobs.PROJID = projects.PROJID
JOIN biditems ON projects.id = biditems.project_id
JOIN details' . $type['type'] . ' on jobs.JOBNO = details' . $type['type'] . '.JOBNO
WHERE jobs.PROJID = :pid
GROUP BY jobs.JOBNO
) AS temp ON jobs.JOBNO = temp.JOBNO
SET jobs.VALUE = JOBSVALUE';
$command=$connection->createCommand($sql);
$command->bindValue(":pid", $model->PROJID,PDO::PARAM_INT);
$command->execute();
$sql = "UPDATE jobs j
JOIN (
SELECT j.JOBNO, COUNT(l.JOBNO) AS numlis
FROM lineitems l
RIGHT JOIN jobs j ON j.JOBNO = l.JOBNO
WHERE j.PROJID = :pid
GROUP BY j.JOBNO
) t ON j.JOBNO = t.JOBNO
SET `VALUE` = 0, `EARNED` = 0
WHERE PROJID = :pid AND t.numlis = 0;";
$command=$connection->createCommand($sql);
$command->bindValue(":pid", $model->PROJID,PDO::PARAM_INT);
$command->execute();
1st attempt
$sql = "select jobs.JOBNO, round(details".$type['type'].".".$type['km']." * sum(PRICE),2) AS JOBSVALUE
from jobs
join projects on jobs.PROJID = projects.PROJID
join biditems on projects.id = biditems.project_id
join details".$type['type']." on jobs.JOBNO = details".$type['type'].".JOBNO
where jobs.PROJID = :pid
GROUP BY jobs.JOBNO";
$command=$connection->createCommand($sql);
$command->bindValue(":pid",$model->PROJID,PDO::PARAM_INT);
$result = $command->queryAll();
foreach ($result as $value) {
$job = Jobs::model()->findByPk($value['JOBNO']);
$job->VALUE = $value['JOBSVALUE'];
$job->save();
}
$sql = "SELECT j.JOBNO, COUNT(l.JOBNO) AS numlis
FROM lineitems l
RIGHT JOIN jobs j ON j.JOBNO = l.JOBNO
WHERE j.PROJID = :pid
GROUP BY j.JOBNO";
$command=$connection->createCommand($sql);
$command->bindValue(":pid",$model->PROJID,PDO::PARAM_INT);
$result = $command->queryAll();
foreach ($result as $value) {
if($value['numlis'] == 0){
$job = Jobs::model()->findByPk($value['JOBNO']);
$job->VALUE = 0;
$job->EARNED = 0;
$job->save();
}
}
Just literally following their documentation:
$job = Yii:app()->db
->createCommand()
->select(
'jobs.JOBNO, round(details'.$type['type'].'.'.$type['km'].' * sum(PRICE), 2)'
)
->join('projects', 'jobs.PROJID = projects.PROJID')
->join('biditems', 'projects.id = biditems.project_id')
->join('details'.$type['type'], 'jobs.JOBNO = details'.$type['type'].'.JOBNO')
->where('jobs.PROJID=:pid', array(':pid' = $model->PROJID))
->group('jobs.JOBNO')
->queryRow();
say if I have the query select users.user_id, users.fname, users.lname, bios.bio, groups.groupid from users LEFT JOIN bios on users.user_id = bios.userid then I want to add another table on a condition then add a where statement at the end. The problem is because when I bind the param it said 'number of variables doesn't match the number of variables in the prepare statement'. How would I solve this? Cheers. Example:
$info = "select users.user_id, users.fname, users.lname, bios.bio, groups.groupid from users LEFT JOIN bios on users.user_id = bios.userid";
$content = $members->prepare($info);
if ($_GET['where'] == 'requests') $info .= "LEFT JOIN requests on users.user_id = requests.receiver";
else if ($_GET['where'] == 'referrals') $info .= "LEFT JOIN referrals on users.user_id = referrals.receiver";
$info .= "where users.user_id = ?";
$content->bind_param('s', $_SESSION['token'][1]);
$content->execute();
You're changing the SQL string after preparing it. Don't do that. Do it like this instead:
$info = "select users.user_id, users.fname, users.lname, bios.bio, groups.groupid from users LEFT JOIN bios on users.user_id = bios.userid";
if ($_GET['where'] == 'requests') $info .= " LEFT JOIN requests on users.user_id = requests.receiver";
else if ($_GET['where'] == 'referrals') $info .= " LEFT JOIN referrals on users.user_id = requests.receiver";
$info .= " where users.user_id = ?";
$content = $members->prepare($info);
$content->bind_param('s', $_SESSION['token'][1]);
$content->execute();
Edit: Also, make sure your SQL fragments are separated with spaces where necessary; the .= operator doesn't automatically add a space for you.
I have this codes for Dynamic Query on a search box but i don't have any result for a search word(this word must return several records) while i have output for string($q),appreciate that help me for finding the problem.
<?php
error_reporting(E_ALL);
//include("../mahal/mahal.php");
include("../mahal/mahalmag.php");
$textfieldstring = mysql_real_escape_string($_REQUEST['Textfield1']);
$connmag = mysql_connect($dbhostmag, $dbusermag, $dbpassmag) or die ('Error connecting to Database,this is maybe due to heavy traffic,please refresh your page.');
$dbname = 'magazine';
mysql_select_db("$dbname");
mysql_query('SET NAMES utf8',$connmag); //for utf charachter
$q = strip_tags(trim($textfieldstring));
if($q) {
$search_words = explode(' ', strtolower($q));
for($i = 0; $i < count($search_words); $i++) {
if($i) {
$str_search .= "OR title LIKE '%".mysql_real_escape_string($search_words[$i])."%' OR articlebody LIKE '%".mysql_real_escape_string($search_words[$i])."%' ";
} else {
$str_search = "OR title LIKE '%".mysql_real_escape_string($search_words[$i])."%' OR articlebody LIKE '%".mysql_real_escape_string($search_words[$i])."%' ";
}
}
}
$search_data = "WHERE (".$str_search.")";
$query_search = "SELECT a.articleid, a.title, a.state, SUBSTR(a.articlebody,1,300) AS description1,
p.photofilename, a.deletitem, ac.catid,c.parentid,a.articlebody
FROM tbarticles a
INNER JOIN tbphotos p ON (p.articleid = a.articleid)
INNER JOIN tbarticlecategories ac ON (ac.articleid = a.articleid)
INNER JOIN tbcategories c ON (c.catid = ac.catid)
$search_data AND a.deletitem = '1'";
$result_search = mysql_query($query_search);
$num_rows = mysql_num_rows($result_search);
$query_row = mysql_fetch_assoc($result_search);
echo "$num_rows";
echo "$q";
?>
Update: the extra "OR" has been removed from the case where $i is 0.
When the search term is (for example) "cold", the generated SQL query is:
SELECT a.articleid, a.title, a.state, SUBSTR(a.articlebody,1,100) AS description1,
p.photofilename, a.deletitem, ac.catid,c.parentid,a.articlebody
FROM tbarticles a
INNER JOIN tbphotos p ON (p.articleid = a.articleid)
INNER JOIN tbarticlecategories ac ON (ac.articleid = a.articleid)
INNER JOIN tbcategories c ON (c.catid = ac.catid)
WHERE ( title LIKE '%cold%' OR articlebody LIKE '%cold%' )
AND a.deletitem = '1'
With a search term of "cold play", the query is:
SELECT a.articleid, a.title, a.state, SUBSTR(a.articlebody,1,100) AS description1,
p.photofilename, a.deletitem, ac.catid,c.parentid,a.articlebody
FROM tbarticles a
INNER JOIN tbphotos p ON (p.articleid = a.articleid)
INNER JOIN tbarticlecategories ac ON (ac.articleid = a.articleid)
INNER JOIN tbcategories c ON (c.catid = ac.catid)
WHERE ( title LIKE '%cold%' OR articlebody LIKE '%cold%'
OR title LIKE '%play%' OR articlebody LIKE '%play%' )
AND a.deletitem = '1' but lot of records are not related to search word
You forgot to strip the first OR from $str_search
$search_data = "WHERE (".$str_search.")";
The code should have been
$str_search = '';
for($i = 0; $i < count($search_words); $i++) {
if($i) { $str_search .= " OR "; }
$str_search .= " title LIKE '%".mysql_real_escape_string($search_words[$i])."%' OR articlebody LIKE '%".mysql_real_escape_string($search_words[$i])."%' ";
}
To make it match multiple $search_words where all words must exist in a single articlebody or a single title, then
$str_search_article = '';
$str_search_title = '';
for($i = 0; $i < count($search_words); $i++) {
if($i) {
$str_search_article .= " AND ";
$str_search_title .= " AND ";
}
$search_word = "'%".mysql_real_escape_string($search_words[$i])."%'";
$str_search_title .= " title LIKE " . $search_word;
$str_search_article .= " articlebody LIKE " . $search_word;
}
$search_data = "WHERE ((".$str_search_title.") OR (".$str_search_article."))";