Dynamically created sql not happy - php

I have a table which contains records of a 'widget' many of the columns contain just the Id of a record in a different table. When editing the widget record users are allowed to do a save even if it is incomplete. They can open it later and continue.
The problem I have, is when it is incomplete my query returns nothing because the where clause contain fields which have default 0 in them and there is no match in the other tables. Here is a sample of script which illustrates this problem.
select Client,Make,Model,Shape
from
widget,clients,makes,models,shapes
where
widget.ClientId = '3' and
widget.MakeId = makes.Id and
widget.ModelId = models.Id and
widget.ShapeId = shapes.Id
I am building this query dynamically using PHP so am trying to keep it as simple as possible. All sugestions welcome, thanks.

The problem is that you are using an implicit inner join (implicit meaning that you do the join in the where clause). Inner joins return matching records only, therefore if some of the data are incomplete, no records will be returned.
Use an outer join instead, that return all records from one of the tables in the join and the matching records from the other table (MySQL does not support full outer join, but this is not relevant here anyway).
Based on your description widget table is your main table, so use left join to join all other tables on widget to get the widget even if it is incomplete:
select c.Client, m.make, md.model, s.shape
from widget w
left join clients c on c.id = w.ClientId
left join makes m on m.id = w.MakeId
left join models md on md.id = w.ModelId
left join shapes s on s.id = w.ShapeId

select c.Client, m.make, md.model, s.shape
from widget w
join clients c on c.id = w.ClientId
join makes m on m.id = w.MakeId
join models md on md.id = w.ModelId
join shapes s on s.id = w.ShapeId
Use Joins instead of multiple tables in FROM Clause.

Instead of direct join use LEFT JOIN so that no matter if there is records from other tables, still first table entries will be returned:
SELECT Client, Make, Model, Shape
FROM widget
LEFT JOIN clients ON widget.ClientId = widget.Id
LEFT JOIN makes ON widget.MakeId = makes.Id
LEFT JOIN models ON widget.ModelId = models.Id
LEFT JOIN shapes ON widget.ShapeId = shapes.Id
WHERE widget.ClientId = 3
Table columns should be in lower case
Table names should be in singular form, e.g. model, shape
Foreign keys should be in other table. Instead of widget having ModelId, model should have widget id
I may be wrong if relations are different

Related

SQL: 3 Table Inner Join Returns Multiple Results

SELECT video.name, video.description, video_source.url, bitcast_user.username
FROM video
INNER JOIN bitcast_user ON video.account_id = bitcast_user.id
INNER JOIN video_source ON video_source.video_id = {$_GET['id']};
This returns results with incorrect video names, descriptions and associated accounts but correct sources. There is a one-to-many relationship between users and videos, and videos and sources.
You shouldn't do an INNER JOIN on a variable - that belongs in the WHERE clause. (Actually - I was even surprised that this worked at all.) I think you need a query like this:
SELECT video.name, video.description, video_source.url, bitcast_user.username
FROM video
INNER JOIN bitcast_user ON video.account_id = bitcast_user.id
INNER JOIN video_source ON video_source.video_id = video.video_id
WHERE video_source.video_id = {$_GET['id']};
(I'm not sure about video_source.video_id = video.video_id because I don't know how the column is named in the video table.)

PHP MySQL query WHERE equals AND row does not exist

I have been looking and cant find an answer to what im trying to do.
I dont know if a query can be created in the following way.
$sql_call = "SELECT table.item,table.item,table.item FROM cust
LEFT JOIN contact ON cust.id = contact.client_id
LEFT JOIN survey_audit ON cust.id = survey_audit.cust_id
WHERE cust.clinic='$clinic_id' AND contact.participate='1' AND survey_audit.survey_id != '$post_survey_id'";
The query above, does not do what Im trying to do, and that is:
Get data from tables WHERE cust.clinic=something AND contact.participate=something AND (this is the part im not sure about) inside Survey_audit table, there is no row with this id.
Is it possible to ask sql to find a result where something=something AND is no row in specific table?
You are sort of on the right track. You simply need to look for cases where survey_audit.survey_id is NULL.
SELECT table.item,table.item,table.item
FROM cust
LEFT JOIN contact
ON cust.id = contact.client_id
LEFT JOIN survey_audit
ON cust.id = survey_audit.cust_id
WHERE cust.clinic='$clinic_id'
AND contact.participate='1'
AND survey_audit.survey_id IS NULL
Here is a very useful resource for helping you determine how to form more complex join scenarios. Your case is the 4th example on this page.
http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
You can exclude all the elements of the table using a subquery:
$sql_call = "SELECT table.item,table.item,table.item FROM cust
LEFT JOIN contact ON cust.id = contact.client_id
LEFT JOIN survey_audit ON cust.id = survey_audit.cust_id
WHERE cust.clinic='$clinic_id' AND contact.participate='1' AND survey_audit.survey_id NOT IN (SELECT survey_id FROM Survey_audit);
Yes it is possible, you should read more about other types of joins in mysql there are 4 types of joins
INNER JOIN (JOIN) - matching id's in both tables
LEFT JOIN - matching id in table A and can be null in Table B
RIGHT JOIN - matching id in table B and can be null Table A
OUTER JOIN - can be null in both tables
Recommend you to read the following article
http://www.sitepoint.com/understanding-sql-joins-mysql-database/
So for your question I guess you should use RIGHT JOIN survey_audit instead of LEFT JOIN survey_audit

MySQL returning same data different rows

I am trying to get data from reviews table then, join the same table again but find different data (likes) based on the id of the first table (reviews) and find the corresponding description from yet another joined table (descriptions).
I know this might be hard to visualize but maybe someone will know why the likes from the second reviews table return the same data for different rows:
SELECT r.title, co.likes, d.description
FROM reviews r
INNER JOIN reviews co
INNER JOIN reviews_descriptions d
ON co.id = d.review_id
WHERE co.parent = 52
AND r.id = 52;
The result is two rows in which title and likes have the same data while the description field grabs different data (the correct way). Likes should have different data for each row.
Help please.
An alternative for writing this and I believe this is what you are looking for:
SELECT r.title, co.likes, d.description
FROM reviews r, reviews co, review_descriptions d
WHERE co.parent = r.id AND d.review_id = co.id AND r.id = 52;
Since you are matching co.parent to 52 and r.id to 52, then you should have a join on co.parent = r.id, however, you should rarely have to do a join on the same table. I think your tables are poorly formatted or you don't need to do the join in the first place and should be able to use r.likes instead of co.likes.

the whole data from tables is not coming via join query in mysql

i'm working with php mysql and there are 12 tables which contains student informations.There are 3 main table First table is registration, second is demandraft and third is creditcard.The demandraft table contains all the creditcard table fields but as empty. now i want to get the whole data from these three tables to generate my xls file but coz there are empty fields of creditcard table in demandraft table so unable to fetch the whole records from all 3 tables. there is stuid field common in all 3 tables.
Here is my join query for that:
$sql = "select * from registration
join programme on registration.id=programme.stuid
join family on registration.id=family.stuid
join address on registration.id=address.stuid
join education on registration.id=education.stuid
join extradetail on registration.id=extradetail.stuid
join workexperience on registration.id=workexperience.stuid
join demanddraft on registration.id=demanddraft.stuid
join payonline on registration.id=payonline.stuid
where (DATE(registration.createddate)>='".$term1."'
AND DATE(registration.createddate)<='".$term2."')";
Use a left join.
select *
from a join b on a.id = b.a_id
will not list lines of table a that do not appear in table b.
select *
from a left join b on a.id = b.a_id
will.
Left join might be a bit tricky when chaining many of them with multiple tables. You may have to cleverly use parentheses around joins such that the order of joins is correct.
This :
$sql = "select * from registration
left join programme on registration.id=programme.stuid
left join family on registration.id=family.stuid
left join address on registration.id=address.stuid
left join education on registration.id=education.stuid
left join extradetail on registration.id=extradetail.stuid
left join workexperience on registration.id=workexperience.stuid
left join demanddraft on registration.id=demanddraft.stuid
left join payonline on registration.id=payonline.stuid
where (DATE(registration.createddate)>='".$term1."'
AND DATE(registration.createddate)<='".$term2."')";
Should do the trick

Join mysql with multiple queries

I have three different SQL tables I need to join:
table "internet" with columns id|type|status
table "type_list" with columns id|type_name
table "status_list" with columns id|status_name
I want to output text from the two other tables (type_list, status_list) but not values as numbers which currently I have in table "internet".
I also don't want to make lazy programming - PHP array to make ID's equal to something like
$type_list = array("1"=>"VDSL2","2"=>"ADSL");
$status_list = array("1"=>"Pending","2"=>"Active");
because the text is already in the tables, i just dont know how to join them and output the text as query combined together in one query.
Use JOIN
SELECT i.id, type_name, status_name
FROM internet i
LEFT OUTER JOIN type_list t ON t.id = i.type
LEFT OUTER JOIN status_list s ON s.id= i.status
Read the MySQL doc for more informations.
Just write the select with the fields you want.
select internet.id,type_name,status_name from internet
inner join type_list
on type_list.id=internet.id
inner join status_list
on status_list.id=internet.id
For this you need a LEFT JOIN, like so:
SELECT i.id, t.type_name, s.status_name
FROM internet AS i
LEFT JOIN type_list AS t ON t.id = i.id
LEFT JOIN status_list AS s ON s.id= i.id
From your question, it is unclear what field you would like to join the queries on. In the above example, the queries are joined on the id field.
Please also note that the AS is not actually necessary, I have just put it in there to make it clear what is going on

Categories