PHP MySQL query WHERE equals AND row does not exist - php

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

Related

How to join hierarchical table in MySQL (table joins other table that joins other table that joins other table)?

I have 3 tables, tb_item, tb_branch, tb_department, tb_division.
As you can see:
tb_division is under tb_department
tb_department is under branch
tb_branch has no superior
for example if I want to retrieve item_id 1 or 2 or 3 then this should be the result
If I want to retrieve item_id 2 then it will show the department and branch.
My problem is that I can nested join them if if I know the item is related to a specific table but in this case since tb_item can be related to tb_division or tb_department and tb_branch I don't know what query should I formulate.
Changing the database design is not an option since this design is already implemented.
SELECT column-names
FROM table-name1 JOIN table-name2
ON column-name1 = column-name2
WHERE condition
Never Mind guys. I managed to solved it myself. been struggling since I thought I need to do tons of subqueries. Thanks for the answers tho.
SELECT
i.item_id,
dv.division_name,
COALESCE(dept.department_name, dept2.department_name) AS department_name,
COALESCE(br.branch_name, br2.branch_name, br3.branch_name) AS branch_name
FROM
tb_item AS i
LEFT JOIN
tb_division AS dv
ON i.division_id = dv.division_id
LEFT JOIN
tb_department AS dept2
ON dv.department_id = dept2.department_id
LEFT JOIN
tb_branch AS br2
ON dept2.branch_id = br2.branch_id
LEFT JOIN
tb_department AS dept
ON i.department_id = dept.department_id
LEFT JOIN
tb_branch AS br3
ON dept.branch_id = br3.branch_id
LEFT JOIN
tb_branch AS br
ON i.branch_id = br.branch_id

Is it possible with MySQL to generate a query to fetch from several tables even if one has no results?

I'm facing a problem here:
I'm building a forum, this forum has several tables and I'm trying to fetch the comments and user info in a single query.
So far, it should be easy, the problem is that I can't change the structure and with the following query I get a perfect result IF there is a like to the answer. If no one likes the answer it fails.
Select
mfr.mfr_forum_answers.id,
mfr.mfr_forum_answers.date_created,
mfr.mfr_forum_answers.last_updated,
mfr.mfr_forum_answers.content,
mfr.mfr_forum_answers.accepted,
mfr.mfr_forum_answers.user_id,
mfr.mfr_users.level,
mfr.mfr_users.avatar,
mfr.mfr_forum_likes.subject_id,
mfr.wp_users.ID As ID1,
mfr.mfr_forum_topics.user_id As owner_id,
(SELECT count(mfr.mfr_forum_likes.id) FROM mfr.mfr_forum_likes WHERE mfr.mfr_forum_likes.subject_id = :id AND mfr.mfr_forum_likes.type = 'answer') as likes,
(SELECT count(mfr.mfr_forum_likes.id) FROM mfr.mfr_forum_likes WHERE mfr.mfr_forum_likes.subject_id = :id AND makefitreal.mfr_forum_likes.type = 'answer' AND mfr.mfr_forum_likes.user_id = :sessionId ) as i_like,
mfr.wp_users.user_nicename
From
mfr.mfr_forum_likes Inner Join
mfr.mfr_forum_answers
On mfr.mfr_forum_answers.topic_id =
mfr.mfr_forum_likes.subject_id Inner Join
mfr.mfr_users
On mfr.mfr_forum_answers.user_id = mfr.mfr_users.id
Inner Join
mfr.wp_users
On mfr.mfr_users.id = mfr.wp_users.ID Inner Join
mfr.mfr_forum_topics
On mfr.mfr_forum_answers.topic_id = mfr.mfr_forum_topics.id
Where
mfr.mfr_forum_answers.topic_id = :id
And
mfr.mfr_forum_likes.type = 'answer'
So far as said it returns only if an answer has a like, I'm thinking on adding a add to the user who posts the answer by default but I'm trying to improve my skills by solving new issues.
If someone has a suggestion in how I could overcome the fact that if a table is empty, the query continues I'd be really thankfull.
Thanks in advance-
Pihh
Yes. What you are looking for are called left and right joins. According to the documentation, with a LEFT JOIN you still join two tables as normal but
If there is no matching row for the right table in the ON or USING part in a LEFT JOIN, a row with all columns set to NULL is used for the right table.
This means that you can try to join two tables, but if a row does not have any results it will still return the results from the first table. The same is true for a RIGHT JOIN only it works the opposite way: it will return results if the tabled being joined to has results, but the original table does not.
It looks like you have 3 tables for 3 relationships: there are answers, a user gives an answer, and an answer might or might not have like. To grab this data, I would suggest starting from your answers table, performing an INNER JOIN on your users table (assuming there are always users), and a LEFT JOIN on your likes table. Here is a simple example:
SELECT *
FROM answers
INNER JOIN users ON users.id = answers.user_id
LEFT JOIN likes ON likes.answer_id = answer.id
WHERE answers.id = :id
AND likes.type = 'answers'
Of course, if for some unknown reason you need to start from your likes table, then you'd have to RIGHT JOIN the other tables. I hope that gives you a good idea of how you'd make your query.

MySQL Inner Join involving three tables

I am working with four tables:
query,
store,
cluster_group,
tv_region
I want to retrieve query records belonging to a particular TV Region record.
A query record either belongs to a record in the store or cluster_group tables. The query table has 'store_id' and 'cluster_group_id' columns. Either will be null whilst the other will refer to a record in the store or cluster_group table. The store and cluster_group tables both have a 'tv_region_id' column.
To retrieve query records that belong to a TV Region record that has an id = 2, I wrote the following SQL statement:
SELECT query.id AS query_id, cluster_group.name as cluster_name, cluster_group.tv_region_id as cluster_tv_region, store.store_name
FROM query
INNER JOIN cluster_group
ON cluster_group.id=query.cluster_group_id
INNER JOIN store
ON store.id=query.store_id
WHERE cluster_group.tv_region_id = 2
AND store.tv_region_id = 2;
The problem is that it returns zero records even though there are query records that belong to the specified TV Region (via a cluster group or store record). I may have misunderstood how 'inner join' works.
I'm working with Doctrine 2 and have attempted the query using the left join but it still returns nothing, I guess this is because its returning null values too. How do I get it to return only the query records I am interested in and no null values?
Appreciate if someone can point me in the right direction to retrieve the relevant query records.
You will need to use OUTER joins, or possibly LEFT
INNER joins will only return data where there is a matching record on both sides. As you state in your question you only get a match on one side or the other, therefore there is never going to be a matching record across both store and cluster
Jeff Atwood has a good explanation of the join types on his blog http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
Try this:-
SELECT query.id AS query_id, cluster_group.name as cluster_name, cluster_group.tv_region_id as cluster_tv_region, store.store_name
FROM query
LEFT OUTER JOIN cluster_group
ON cluster_group.id=query.cluster_group_id
AND cluster_group.tv_region_id = 2
LEFT OUTER JOIN store
ON store.id=query.store_id
AND store.tv_region_id = 2
EDIT - no experience of doctrine, but you could try using a UNION:-
SELECT query.id AS query_id, cluster_group.name as cluster_name, cluster_group.tv_region_id as cluster_tv_region, NULL AS store_name
FROM query
INNER JOIN cluster_group
ON cluster_group.id=query.cluster_group_id
AND cluster_group.tv_region_id = 2
UNION
SELECT query.id AS query_id, NULL as cluster_name, NULL as cluster_tv_region, store.store_name
FROM query
INNER JOIN store
ON store.id=query.store_id
AND store.tv_region_id = 2
It works like this for me:
from table1 inner join table2 on table1.id = table2.id
inner join table3 on table1.id = table3.id

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

mysql join select explained

I have two tables: 'posts' and 'users' every post has a 'ref_id' column to get the user id who posted it.
Now, I am getting posts this way:
$this->db->query("SELECT * FROM posts WHERE time > '$timeLimit' LIMIT 50");
I can't understand how to join every result to get the poster related data as well. What I am doing right now is basically a loop inside a loop, where foreach of the result, get their user info. But it is pretty obvious that this is very wrong,
Apparently I need to start using joins, but how does one do it? this should be a really simple example to work with, I suppose.
Any help? Thank you.
SELECT posts.*, users.*
FROM posts
INNER JOIN users
ON posts.posted_by = users.id;
Like this:
SELECT
posts.*,,
users.Username
FROM posts
INNER JOIN users ON posts.ref_id = users.user_id;
Explanation:
To JOIN to any tables with each others, there are two things; the JOIN type and the join condition. There are three main types of join:
INNER JOIN, only the rows that match the join condition will be returned from the two tables no more rows. But:
LEFT OUTER JOIN, when you join two tables you will have one on the left of the join keyword and the other one will be in the right:
FROM Table1 <------------- This is the left table.
LEFT OUTER JOIN table2 .... <------------- This is the right table.
In LEFT OUTER JOIN the unmatched rows from the left table will be included in the result set.
RIGHT OUTER JOIN the unmatched rows from the right table will be included in the result set.
CROSS JOIN this will perform a Cartesian product from the two tables.
In our query, the query will reutrn all the users from the users table only if the ref_id equal to the user_id column form the posts table.
For more information and explanations:
A Visual Explanation of SQL Joins.
Another Visual Representation of SQL Joins.
Join syntax in MySQL
SELECT user.name
FROM users
INNER JOIN posts
ON posts.ref_id == user.id
AND posts.time > 50
http://www.w3schools.com/sql/sql_join_inner.asp

Categories