Select from Multiple table, but ignore if not found - php

Using this query I'm selecting rows from multiple tables. Unfortunately, if a row does not exist in one table, then rows in all tables won't return. It's because I'm using AND operator.
So, I want this query to be modified, where will ignore a table if value is not found, but return rest of the tables where the value is found.
Here's the MySQL query:
foreach ($courseArr as $term) {
$term = trim($term);
if (!empty($term)) {
$courseSectionSql[] = "courseDataApp.course = '$term' AND courseDataApp.section = '$sectionArr[$i]'";
$i++;
}
}
$data = $db->rawQuery("SELECT courseDataApp.*, facultyDatabase.*, books.*
FROM courseDataApp
INNER JOIN facultyDatabase ON facultyDatabase.initial = courseDataApp.faculty
INNER JOIN books ON books.course = courseDataApp.course WHERE ".implode(' OR ', $courseSectionSql));
Here's what is returns:
{
"id":11,
// courseDataApp values
"faculty":"AKH1",
"course":"CSE241",
"section":"7",
.
.
.
.
.
.
.
// facultyDatabasevalues
"initial":"AKH1",
"name":"Ms. Kamal Habi",
"dept":"ECE",
.
.
.
.
.
.
// books values
"books": "Digital Logic Design"
},
So the problem is, when a value from facultyDatabase or books tables not found, rest of the data won't return. I just want it to ignore that, show what's found. Like Union.

As some of the comments point out you are using outdated syntax that INNER JOINs the tables which leads to the result you get. You need to LEFT JOIN the tables. Hence you will have a result even though there are no entries in the LEFT JOINed tables. Something like this should work
SELECT courseDataApp.*, facultyDatabase.*, books.*
FROM courseDataApp
LEFT JOIN facultyDatabase ON facultyDatabase.initial = courseDataApp.faculty
LEFT JOIN books ON books.course = courseDataApp.course
WHERE courseDataApp.course = '$term'
AND courseDataApp.section = '$sectionArr[$i]'
Written like this you would have an equivalent to your query in current syntax that will not return anything if there are no entries in the INNER JOINed tables.
SELECT courseDataApp.*, facultyDatabase.*, books.*
FROM courseDataApp
INNER JOIN facultyDatabase ON facultyDatabase.initial = courseDataApp.faculty
INNER JOIN books ON books.course = courseDataApp.course
WHERE courseDataApp.course = '$term'
AND courseDataApp.section = '$sectionArr[$i]'

Related

MySql query duplicating results (with certain parameters)

I have a fairly complex query (to me) that returns duplicate results ONLY when the parameter passed results in 'dest_xdock: ' . $row['dest_xdock'] as a certain value. Can anyone identify why this is happening in the Query? I don't have duplicates of this in the table that I can see. Here is the query:
select
`orig_lookup`.`zipcode` AS `orig_zipcode`,
`orig_lookup`.`state` AS `orig_state`,
`orig_lookup`.`svcnotes` AS `orig_svcnotes`,
`orig_lookup`.`svcterms` AS `orig_svcterms`,
`orig_lookup`.`daysout` AS `orig_daysout`,
`orig_lookup`.`daysin` AS `orig_daysin`,
`orig_lookup`.`pcity` AS `orig_city`,
`orig_lookup`.`scac` AS `orig_scac`,
`orig_lookup`.`xdock` AS `orig_xdock`,
`orig_lookup`.`scac2` AS `orig_scac2`,
`orig_lookup`.`xdock2` AS `orig_xdock2`,
`orig_lookup`.`scac3` AS `orig_scac3`,
`orig_lookup`.`xdock3` AS `orig_xdock3`,
`orig_ssas`.`ssa` AS `orig_ssa`,
`orig_hcas`.`hca` AS `orig_hca`,
`dest_lookup`.`zipcode` AS `dest_zipcode`,
`dest_lookup`.`state` AS `dest_state`,
`dest_lookup`.`svcnotes` AS `dest_svcnotes`,
`dest_lookup`.`svcterms` AS `dest_svcterms`,
`dest_lookup`.`daysout` AS `dest_daysout`,
`dest_lookup`.`daysin` AS `dest_daysin`,
`dest_lookup`.`pcity` AS `dest_city`,
`dest_lookup`.`scac` AS `dest_scac`,
`dest_lookup`.`xdock` AS `dest_xdock`,
`dest_lookup`.`scac2` AS `dest_scac2`,
`dest_lookup`.`xdock2` AS `dest_xdock2`,
`dest_lookup`.`scac3` AS `dest_scac3`,
`dest_lookup`.`xdock3` AS `dest_xdock3`,
`dest_ssas`.`ssa` AS `dest_ssa`,
`dest_hcas`.`hca` AS `dest_hca`,
`tbl_matx_20160321`.`trmnljoin` AS `TrmnlMatx`,
`tbl_matx_20160321`.`trmnlsvcdays` AS `TrmnlSvcDays`,
`tbl_matx_20160321`.`trmnltranspts` AS `TrmnlTransPts`,
IF(ISNULL(`orig_lookup`.`daysin`+ `dest_lookup`.`daysout`+ `tbl_matx_20160321`.`trmnlsvcdays`), 'No Service',(`orig_lookup`.`daysin`+ `dest_lookup`.`daysout`+ `tbl_matx_20160321`.`trmnlsvcdays`)) AS `TotalSvcDays`
FROM ((`tbl_uscomp_20160321` AS `orig_lookup` LEFT JOIN `tbl_hcas_20160321` AS `orig_hcas` ON `orig_lookup`.`zipcode` = `orig_hcas`.`zipcode` LEFT JOIN `tbl_ssas_20160321` AS `orig_ssas` ON `orig_lookup`.`zipcode` = `orig_ssas`.`zipcode`)
INNER JOIN (`tbl_uscomp_20160321` AS `dest_lookup` LEFT JOIN `tbl_hcas_20160321` AS `dest_hcas` ON `dest_lookup`.`zipcode` = `dest_hcas`.`zipcode` LEFT JOIN `tbl_ssas_20160321` AS `dest_ssas` ON `dest_lookup`.`zipcode` = `dest_ssas`.`zipcode`)
INNER JOIN `tbl_matx_20160321` ON (`orig_lookup`.`xdock` = `tbl_matx_20160321`.`otrmnl` AND `dest_lookup`.`xdock` = `tbl_matx_20160321`.`dtrmnl`))
WHERE `orig_lookup`.`zipcode` = '$ziporig' AND `dest_lookup`.`zipcode` = '$zipdest'",

php mysql three left join method

I have three table:
Article:
|id|title|timestamp|......
group_tags:
|id|content_id|tags_id
tags_name:
|id|name|
I need to list article title with any tag id:
function _tags_search_($id,$type){
$DB_QUERY = mySqli::f("SELECT title FROM " . ARTICLES . " LEFT JOIN " . POSTS_TAGS . " ON " . ARTICLES . ".id = " . POSTS_TAGS . ".content_id WHERE
" .POSTS_TAGS . ".tags_id = ? AND approved = 1 ORDER BY timestamp DESC LIMIT 12", $id);
foreach($DB_QUERY as $row){
$data[] = $row;
}
return $data;
}
this worked for me and show list of article title.
But I need to show tag name for tags id in addition to list title like this:
Search result for : Linux
I have two way :
three left join method ( if true how do?)
fetch another query for show tag name.
I think three join is better and faster. how do show tags name with three join method?!
try this
SELECT title, name from
group_tags g
INNER JOIN article ON a.id = g.content_id
INNER JOIN tags_name t ON t.id = g.tags_id
Let me know if you face any issue

Codeigniter not showing proper results for array fetched by MySQL query.

I am working with Codeigniter with mysql databases,
I have a model function
public function get_all_data(){
$this->output->enable_profiler(TRUE);
$years = $this->input->post('year');
$months = $this->input->post('month');
$exec_ids = $this->input->post('exec_id');
$query = $this->db->query("SELECT * FROM client_booking AS cb
RIGHT OUTER JOIN executive_client_unit_relation AS ecur ON cb.id = ecur.booking_id
LEFT OUTER JOIN new_invoice ON cb.id = new_invoice.booking_id
WHERE ecur.executive_id IN (" . implode(',', $exec_ids) . ") AND MONTH(cb.booking_date) IN (" . implode(',', $months) . ") AND YEAR(cb.booking_date) IN (" . implode(',', $years) . ")");
return $query->result();
}
The sql generated by this is (as seen in the profiler) :
SELECT * FROM client_booking AS cb
RIGHT OUTER JOIN executive_client_unit_relation AS ecur ON cb.id = ecur.booking_id
LEFT OUTER JOIN new_invoice ON cb.id = new_invoice.booking_id
WHERE ecur.executive_id IN (4,5,6) AND MONTH(cb.booking_date) IN (1,2,3,4,5) AND YEAR(cb.booking_date) IN (2013,2014)
My problem is that the booking_id value is set to NULL when I var_dump() the result of this query.
On the other hand, when I run the SQL in my phpmyadmin, everything goes well and I can see the booking_id
PS: client_booking table's primary key is id which is the booking_id for all the other tables.
Can anyone help me to resolve this?
You are using LEFT/RIGHT joins so when there is no association found between your tables a null row will be returned ,second thing is your tables new_invoice and executive_client_unit_relation both have common names for the column name booking_id and in your select statement you are doing select * so for the columns with same name i guess the last one is picked which is null,for the solution you either you select only needed columns not all like SELECT cb.* or either the columns have same name with your query table then specify them individually with the alias you wish to provide but in the end of select statement in query like SELECT *,cb.id AS booking_id,....

SQL - join 2 tables but return all if 1 table empty

Using CodeIgniter Active Records:
$country = $_SESSION['search'];
$min_price = $_SESSION['min_price'];
$max_price = $_SESSION['max_price'];
$condition = "";
$this->db->select('*,attachments.title as image');
$this->db->from('details');
$this->db->join('attachments', 'attachments.parent = details.id');
$this->db->where('attachments.type', 'quotes');
if ($country != '')
{
$condition .= "(details.service_location IN ('" . $country . "') OR details.country in ('" . $country . "'))";
$this->db->where($condition);
}
$this->db->where('details.price_range_from >=', $min_price);
$this->db->where('details.price_range_to <=', $max_price);
$this->db->group_by("attachments.parent");
$this->db->order_by("details.created_on", "asc");
$query = $this->db->get();
$result = $query->result();
return $result;
}
I have 2 tables say details and attachments, and I want to do a join on them.
Table details will always have records in it.
When table attachments has rows in it, I want the query to turn all the rows in which table details and table attachments matches. (i.e. behave like inner join)
However, if table attachments is empty, I'd like to return everything from table details.
and also checking table attachments in where condition.
Is this possible to do in 1 query?
Thanks.
Use LEFT OUTER JOIN rather than JOIN
FROM (details)
LEFT OUTER JOIN attachments ON attachments.parent = details.restaurant_id
UPDATE
and of course
GROUP BY details.restaurant_id
rather than attachments.parent
Although I think it's a bit weird requirement, the principal structure you can use is:
inner join
union
select *, ... from details where 0 = (select count(*) from attachments where ...)
If the inner join doesn't return rows, the second query will return all details.
If the inner join returns rows, the second query won't return anything because attachments are found (count(*) returns some positive value).
I think you can fill in the details yourself.
I don't guarantee for brilliant performance.
Use two different queries, check if attachments has rows and run query with inner join details else return rows from details table
IF EXISTS (SELECT * FROM #attachments where column1='')
BEGIN
SELECT * FROM attachments as atc
INNER JOIN details AS det ON atc.parent = det.restaurant_id where column2=''
END
ELSE
SELECT * FROM details where column2=''

MySQL - Datas all included in larger data set

So I have 2 tables:
user_selection (id, user_id, fiche_id)
fiche (id, title, ...)
(fiche = sheet)
I have a research request which gives me some fiche ids
SELECT fiche.*, IF(fiche.fiche_type_id = 2,fiche.instance,fiche_type_texte.type_texte) AS type_texte, IF(fiche.fiche_type_id = 2,CONCAT(fiche.affaire," - ", fiche.titre),fiche.titre) AS titre, IF(fiche.fiche_type_id = 1,fiche.date_publication,fiche.date_texte) AS date_publication
FROM enviroveille_bascule.fiche
LEFT JOIN enviroveille_bascule.fiche_type_texte ON(fiche.fiche_type_texte_id = fiche_type_texte.id)
LEFT JOIN enviroveille_bascule.fiche_x_keyword ON(fiche_x_keyword.fiche_id = fiche.id)
LEFT JOIN enviroveille_bascule.fiche_x_theme ON(fiche_x_theme.fiche_id = fiche.id)
LEFT JOIN enviroveille_bascule.fiche_echeance ON(fiche_echeance.fiche_id = fiche.id)
LEFT JOIN enviroveille_bascule.fiche_x_activite ON(fiche_x_activite.fiche_id = fiche.id) LEFT JOIN enviroveille_bascule.fiche_x_nomenclature ON(fiche_x_nomenclature.fiche_id = fiche.id)
WHERE 1 = 1
AND fiche_echeance.fiche_echeance_type_id IN(2)
GROUP BY fiche.id
I'd like to know if all results from my research query is in the user selection.
So I tried :
// fiche_ids is an array of fiche.id resulting from research request
SELECT COUNT(*) AS nb
FROM " . $this->bdd . $this->table_user_selection . "
WHERE user_id = '" . $user->datas_user['id'] . "'
AND fiche_id IN ('" . implode("','", $fiche_ids) . "')
if($ds['nb'] == count($fiche_ids) && count($fiche_ids) > 0) {
return true;
} else {
return false;
}
That works well
Problem is that I have some research request giving 10K+ results.
And I have to do it several time on the same page, which makes server lags.
Is there a easy way to know if all my results are in my selection?
Note that selection may contain more fiche_id than the research result.
The best would be to be able do this in one SQL request.

Categories