need help for my query - mysql

I need help for my query:
SELECT
P.ID,
P.CategoryID,
P.Name,
P.SupplierID,
p.UnitPrice,
p.UnitsInStock,
pp.PicturePath
FROM Products P JOIN ProductPhoto PP ON p.ID=PP.ProductID WHERE P.CategoryID='2';
This query gives me 2 results but it must give me 4 result because there are 4 data whose categoryID='2'
Also I have checked from this query and there are 4 data whose categoryID='2'
select * from Products;

You will want a LEFT JOIN:
SELECT P.ID,
P.CategoryID,
P.Name,
P.SupplierID,
p.UnitPrice,
p.UnitsInStock,
pp.PicturePath
FROM Products P
LEFT JOIN ProductPhoto PP
ON p.ID=PP.ProductID
WHERE P.CategoryID='2'
A LEFT JOIN will return all Products even if there is no matching row in the ProductPhoto table. The INNER JOIN will only return rows that match in both tables.
If you need help learning JOIN syntax then here is a great visual explanation of Joins

SELECT
P.ID,
P.CategoryID,
P.Name,
P.SupplierID,
p.UnitPrice,
p.UnitsInStock,
pp.PicturePath
FROM Products P LEFT JOIN ProductPhoto PP ON p.ID=PP.ProductID WHERE P.CategoryID='2'
Try use left join, it is possible that there is no productionPhoto records matching product.

Note that you are doing an INNER JOIN onto ProductPhoto on the ProductID which equals the ID within Products.
If there are only 2 matching rows in both tables with a categoryID of 2, then that's all you will see returned.
Change your query to be a LEFT JOIN and see if your 4 rows returned. If they are, then your above query is correct.

Related

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?

Using two inner join tables

I have come up with two queries, both use an inner join on two different tables.
Query 1
SELECT PRODUCTS.CODE, PRODUCTS.REFERENCE, PRODUCTS.TAXCAT, PRODUCTS.DISPLAY,PRODUCTS.NAME, PRODUCTS.PRICEBUY, PRODUCTS.PRICESELL, CATEGORIES.NAME AS CATEGORY
FROM PRODUCTS INNER JOIN CATEGORIES ON PRODUCTS.CATEGORY = CATEGORIES.ID;
Query 2
SELECT PRODUCTS.CODE, PRODUCTS.REFERENCE, PRODUCTS.TAXCAT, PRODUCTS.DISPLAY,PRODUCTS.NAME, PRODUCTS.PRICEBUY, PRODUCTS.PRICESELL,STOCKCURRENT.UNITS AS UNIT FROM PRODUCTS INNER JOIN STOCKCURRENT ON STOCKCURRENT.PRODUCT = PRODUCTS.ID;
Both queries run fine on their own, when I try to use both inner joins together I get errors. This is what I came up with on my own. I'm having trouble understanding the syntax to achieve this.
SELECT PRODUCTS.CODE, PRODUCTS.REFERENCE, PRODUCTS.TAXCAT,
PRODUCTS.DISPLAY,PRODUCTS.NAME, PRODUCTS.PRICEBUY,
PRODUCTS.PRICESELL,STOCKCURRENT.UNITS AS UNIT FROM PRODUCTS INNER JOIN
STOCKCURRENT ON STOCKCURRENT.PRODUCT = PRODUCTS.ID, CATEGORIES.NAME AS
CATEGORY FROM PRODUCTS INNER JOIN CATEGORIES ON PRODUCTS.CATEGORY =
CATEGORIES.ID;
Thank you.
Your attempted query has several syntax problems. Assuming you just want to join together the three tables, you may try the following query:
SELECT
p.CODE,
p.REFERENCE,
p.TAXCAT,
p.DISPLAY,
p.NAME,
p.PRICEBUY,
p.PRICESELL,
s.UNITS AS UNIT,
c.NAME AS CATEGORY
FROM PRODUCTS p
INNER JOIN STOCKCURRENT s
ON s.PRODUCT = p.ID
INNER JOIN CATEGORIES c
ON p.CATEGORY = c.ID;
Note that I introduced table aliases here. These aliases can be used elsewhere in the query to avoid having to repeat the entire table name.
By the way, I can also see taking a union of your two original queries. But without expected output, it was not entirely clear what you want.

Select distinct returning indistinct rows

Select distinct is returning indistinct rows. Why?
I want to return distinct shops.
Here is my sql statement:
SELECT
DISTINCT s.*, p.p_id
FROM
shop s
INNER JOIN product_shop ps on s.s_id = ps.s_id
INNER JOIN product p ON p.p_id = ps.p_id
WHERE
s.country = 'new zealand'
Here is the result:
The product (p.p_id) needs to not be distinct, as I want to return a list of shops that have a specific product. But the Shop needs to be distinct.
What am I doing wrong?
Returned rows are distinct. Distinct is applied to all returned row, not to single column. Yes, p_id is same for two rows. But if you compare all columns, there are differences between them.
If you want distinct shops - don't include in select columns from other tables, because it can cause duplicates as in your example.
Simply don't include p.p_id within your selection.
I.e.
SELECT DISTINCT
s.*
FROM shop s
....
Well, If you will look at your entire output, you can see the p_id(the last column) is different for each row. Distinct applies to the entire record, not just one column.
You can either drop the p_id from your select, or use group by and decide which one of the p_id you want, perhaps max? :
SELECT
s.*, max(p.p_id)
FROM
shop s
INNER JOIN product_shop ps on s.s_id = ps.s_id
INNER JOIN product p ON p.p_id = ps.p_id
WHERE
s.country = 'new zealand'
GROUP BY s.id

How to left join to select with statement

I have some tables:
products
--------------------------
|p_id|col|col...|...|cat_id|
colors
-----------
|id|p_id|url|
I want select apropriate rows from first table after join to this result another column selected by apropiate id.
In other words I select all products on some cathegory and how many colors each product has.
For example
select *
from products p
where p.p_id = some_number
and join to this
select count(*)
from colors c
where c.p_id = p.p_id
Thanks in advance
Left join return all row of left table(products) even row's id are not match of right table. for more info click here
SELECT p.p_id, COUNT(*) AS colours_count
FROM products AS p
LEFT JOIN colors c
ON c.p_id=p.p_id
GROUP BY p.p_id
Try this:
select p.p_id, count(*) as number_of_colours
from products as p
left join colors c on c.p_id=p.p_id
group by p.p_id
The LEFT JOIN operation guarantees that all rows of table products will be returned. Grouping by p_id, we get a separate row for each product along with the number of colours each product is associated to.
You can do the LEFT JOIN, but note that this returns a row from the left hand table irrespective of whether there is a matching row on the right hand table. Hence it there is no match or 1 match you will still get 1 row returned. As such if you use COUNT(*) you will get a count of 1.
So get around this you count the occurrences of a field from the right hand table (normally the primary key). Used like this COUNT() returns the count of non null fields, so it will return 0 when there is no matching row on the right:-
SELECT p.p_id,
COUNT(c.id) AS number_of_colours
FROM products p
LEFT OUTER JOIN colors c ON c.p_id = p.p_id
GROUP BY p.p_id

mysql return duplicate records based on same key used in IN CLAUSE

I have the following query
SELECT P.PRICE, P.PRODUCT_ID FROM PRODUCT P WHERE P.PRODUCT_ID IN (41,41)
I need it to return the product record twice due to limitations with the application code.
I am not too familiar with SQL so really stuck, I don't want to run single queries for each product
To make it appear twice, you can do:
SELECT P.PRICE, P.PRODUCT_ID FROM PRODUCT P WHERE P.PRODUCT_ID IN (41)
UNION ALL
SELECT P.PRICE, P.PRODUCT_ID FROM PRODUCT P WHERE P.PRODUCT_ID IN (41)
What the UNION operator does is it essentially "tacks" the result of one query onto the result of another... so in your case, we are "tacking" on the same exact selection so that all rows are duplicated twice in your final result.
However, what you'll probably want to do for more complex queries is use a CROSS JOIN:
SELECT P.PRICE, P.PRODUCT_ID
FROM PRODUCT P
INNER JOIN ...
INNER JOIN ...
CROSS JOIN
(
SELECT NULL UNION ALL
SELECT NULL
) cj
WHERE P.PRODUCT_ID IN (41) AND ... AND ... AND ..
This way, rows will be duplicated as many times as there are SELECT NULL's within the CROSS JOIN subselect, and the JOIN and WHERE conditions of the main query only need to be executed once.
The nice thing about using CROSS JOIN is that you don't need to evaluate a join condition, it simply makes a Cartesian product between two sets of data.
Simply tack on the CROSS JOIN at the end of all of your main JOIN operations to manually duplicate your data.
Try this::
SELECT P.PRICE, P.PRODUCT_ID FROM PRODUCT P WHERE P.PRODUCT_ID=41
UNION ALL
SELECT P.PRICE, P.PRODUCT_ID FROM PRODUCT P WHERE P.PRODUCT_ID=41
Another way (using UNION ALL in an internal level). Easier to combine with complex queries (as you mention in the comments):
SELECT p.price, p.product_id
FROM
PRODUCT AS p
JOIN
( SELECT 41 AS product_id
UNION ALL
SELECT 41
) AS selection
ON p.product_id = selection.product_id ;
A cartesian product (vary similar to a cross-join):
SELECT P.PRICE, P.PRODUCT_ID
FROM FROM PRODUCT P
JOIN (values(1),(2) ) AS two ON 1=1
WHERE P.PRODUCT_ID IN (42)
;