What is the difference in mySQL AND vs Where - mysql

I'm using mysql and I confused with "And", "Where"
Somby dy can tell me what is difference between these.
SELECT *,COUNT(comment.id) as comment_count from posts LEFT JOIN comment on posts.post_id =comment.post_id AND comment.approve = 1 GROUP BY posts.post_id
SELECT *,COUNT(comment.id) as comment_count from posts LEFT JOIN comment on posts.post_id =comment.post_id WHERE comment.approve = 1 GROUP BY posts.post_id

They are not the same, first one will return the associations for all, and the second will do it just for the rows in the where match.
In this other duplicate question you can see the full explanation and examples
SQL JOIN - WHERE clause vs. ON clause

Simply change the query to use an inner join like this:
select tableA.id, tableA.name, tableB.details
from tableA
inner join tableB ...
here is the definition of left join:
The LEFT JOIN (also called LEFT OUTER JOIN) keyword returns all rows from the left table (table_name1), even if there are no matches in the right table (table_name2).
whereas the definition of the inner join is:
The INNER JOIN keyword return rows when there is at least one match in both tables.

Related

why is inner join causing query to show only results with not null column?

I'm running the query below and it is working well.
SELECT
stock_parts.title,
COUNT(*) as qtyAvailable,
SUM(shipments.item_cost) as totalValue,
### stock_alerts.minimum
FROM
stock_items
INNER JOIN stock_parts ON stock_items.stock_part_id = stock_parts.id
INNER JOIN shipments ON shipments.id = stock_items.shipment_id
### INNER JOIN stock_alerts ON stock_alerts.stock_part_id = stock_items.stock_part_id
WHERE
stock_items.status IS NULL
AND stock_items.current_stock_id = 1
GROUP BY stock_parts.id
So if I uncomment the two commented lines (is a join to get info from another table), the query results are filtered showing only rows where stock_alerts.minimum is not null.
Why is this happening? I need all results event that column is NULL.
What INNER JOIN does is output the row results where none of the tables have null values on that cell. In other words (from W3 Schools):
The INNER JOIN keyword selects records that have matching values in
both tables
Try using FULL OUTER JOINinstead to get all the records even when one of the tables has a NULL value on it. See the explanation on W3 Schools FULL OUTER JOIN.
EDIT:
I didn't realize one of your tags is MySQL. Here you have a post that explains how to emulate a FULL OUTER JOIN in MySQL
Inner JOIN will ignore NULLS when you do an equal to comparison, I would suggest using IS DISTINCT FROM OPERATOR (<=>)
stock_alerts.stock_part_id <=> stock_items.stock_part_id

Mysql count left join strange result

Can someone help me to understand those results ? (For me all 3 should return 6455).
(Using RDS mysql-8.0.13)
SELECT COUNT(p.product_id) FROM product p LEFT JOIN product_attributes pa ON p.pdt_id = pa.pdt_id WHERE pa.code = 'season';
Results : 6332
SELECT COUNT(*) FROM product p;
Results : 6455
SELECT COUNT(p.product_id) FROM product p LEFT JOIN product_attributes pa ON p.pdt_id = pa.pdt_id AND pa.code = 'season';
Results : 6455
Your first join uses the WHERE clause, this mean sit selected all the rows, including those with a null join and then filters out those WHERE the pa.code = season, i.e. the null joins.
The last one joins on both, but because it is a left join you still get the full table of results, and nothing is filtered because you remove the WHERE clause. If you were to use an INNER JOIN in the last query you should get the same result (6332).
This link might be useful What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?

Issue SQL join query

I am getting issues with the below SQL query, unable to fetch the desired result
SELECT
C.Department__c
,C.Email
,R.AcctID__c
,C.ContactID__c
,R.TransactionDueDate
,R.PubNbr__c
FROM RenewalNotificationProgramDE R
LEFT JOIN ContactNewDE C
ON R.AcctID__c = C.AcctID__c
The idea is to join all the AccountID(AcctID__c) in RenewalNotificationProgramDE table to the corresponding contacts in ContactNewDE table. AccountID is the foreign key in the ContactNewDE table. I am usig Innerjoin in my query as I want all AccountID to map with their corresponding contacts in ContactNewDE.
Just replace LEFT JOIN by INNER JOIN to get all AccountID with their corresponding contacts :-
Use below query :-
SELECT
C.Department__c
,C.Email
,R.AcctID__c
,C.ContactID__c
,R.TransactionDueDate
,R.PubNbr__c
FROM RenewalNotificationProgramDE R
INNER JOIN ContactNewDE C
ON R.AcctID__c = C.AcctID__c
You have used LEFT JOIN in your query, which you need to change it to INNER JOIN. I think you would better to notice the below notes about differences between left and inner joins:
INNER JOIN: Returns all rows when there is at least one match in BOTH
tables
LEFT JOIN: Return all rows from the left table, and the
matched rows from the right table

Left join returning no rows when no row from one of the joined tables is available

SELECT *
FROM `user`
LEFT JOIN `user_group`
ON `user_group`.`userid` = `user`.`userid`
LEFT JOIN `email_template`
ON `email_template`.`user_id`=`user`.`userid`
WHERE `user`.`agent_id`='123'
AND `email_template`.`type`='advertise'
That is my sql statement. I am joining tables user, user group and email_template. The problem is for the user I am querying there is no email_template of type advertise in the table so the entire query returns no rows. Instead I want 1 row, with the email_template type column null.
Did you try moving the email_template filter to the join condition?
Doing this applies the filter on the join instead of the WHERE clause. If you apply the filter on the WHERE then you are basically performing an INNER JOIN which will cause no rows to be returned if nothing meets the criteria:
SELECT *
FROM `user`
LEFT JOIN `user_group`
ON `user_group`.`userid` = `user`.`userid`
LEFT JOIN `email_template`
ON `email_template`.`user_id`=`user`.`userid`
AND `email_template`.`type`='advertise'
WHERE `user`.`agent_id`='123'
move the condition to select email_templatetype='advertise' on the time you are joining. Basically the WHERE clause causes the record to be filtered it does match on the condition.
SELECT *
FROM `user`
LEFT JOIN `user_group`
ON `user_group`.`userid` = `user`.`userid`
LEFT JOIN `email_template`
ON `email_template`.`user_id`=`user`.`userid` AND
`email_template`.`type`='advertise'
WHERE `user`.`agent_id`='123'

MySQL query with LEFT OUTER JOIN and WHERE

I have three tables: stories, story_types, and comments
The following query retrieves all of the records in the stories table, gets their story_types, and the number of comments associated with each story:
SELECT s.id AS id,
s.story_date AS datetime,
s.story_content AS content,
t.story_type_label AS type_label,
t.story_type_slug AS type_slug,
COUNT(c.id) AS comment_count
FROM stories AS s
LEFT OUTER JOIN story_types AS t ON s.story_type_id = t.id
LEFT OUTER JOIN comments AS c ON s.id = c.story_id
GROUP BY s.id;
Now what I want to do is only retrieve a record from stories WHERE s.id = 1 (that's the primary key). I have tried the following, but it still returns all of the records:
SELECT s.id AS id,
s.story_date AS datetime,
s.story_content AS content,
t.story_type_label AS type_label,
t.story_type_slug AS type_slug,
COUNT(c.id) AS comment_count
FROM stories AS s
LEFT OUTER JOIN story_types AS t ON s.story_type_id = t.id
AND s.id = 1
LEFT OUTER JOIN comments AS c ON s.id = c.story_id
GROUP BY s.id;
I have also tried a WHERE clause at the end, which throws an error.
Can someone point out the correct syntax for a condition like this in this situation?
I'm using MySQL 5.1.47. Thanks.
I'm guessing you put the WHERE after the GROUP BY, which is illegal. See this reference on the SELECT syntax in MySQL.
Try this:
SELECT
s.id AS id,
s.story_date AS datetime,
s.story_content AS content,
t.story_type_label AS type_label,
t.story_type_slug AS type_slug,
COUNT(c.id) AS comment_count
FROM
stories AS s
LEFT JOIN story_types AS t ON s.story_type_id = t.id
LEFT JOIN comments AS c ON s.id = c.story_id
WHERE
s.id = 1
GROUP BY
s.id;
editor's note: I reformatted the code to highlight the query structure
Following up this comment on the accepted answer:
It is not intuitive to me that this WHERE would go in the second JOIN
This is just to outline how proper code formatting enhances understanding. Here is how I usually format SQL:
SELECT
s.id AS id,
s.story_date AS datetime,
s.story_content AS content,
t.story_type_label AS type_label,
t.story_type_slug AS type_slug,
COUNT(c.id) AS comment_count
FROM
stories AS s
LEFT JOIN story_types AS t ON t.id = s.story_type_id
LEFT OUTER JOIN comments AS c ON s.id = c.story_id
WHERE
s.id = 1
GROUP BY
s.id;
The WHERE is not on the second join. There is only one WHERE clause allowed in a SELECT statement, and it always is top level.
PS: Also note that in many database engines (apart from MySQL) it is illegal to use a GROUP BY clause and then selecting columns without aggregating them via functions like MIN(), MAX(), or COUNT(). IMHO this is bad style and a bad habit to get into.