Select distinct returning indistinct rows - mysql

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

Related

Mysql (doctrine) - count inner join having count > X

I have SQL to count products with specific properties. I am using it in the products filter. SQL is very long, but here is the primary part:
SELECT COUNT(products.id) as products_count, property_items.description, property_items.id as id
FROM property_items
INNER JOIN product_properties ON property_items.id = product_properties.property_item_id
INNER JOIN products ON product_properties.product_id
INNER JOIN product_properties pp ON products.id = pp.product_id AND (pp.property_item_id IN ($ids))
GROUP BY property_items.id
HAVING COUNT(pp.id) >= $countIds
This works perfectly when I have only the one element in $ids, but when i choose one more, the result is bad. It looks like the sql returns count of all products with any property from $ids, but I need to count only products that contains all properties.
First get all available properties. On each property join products that contains this property and go back to all properties of this product to check, if product contains already checked properties too. Or it is bad idea? I need to keep primary table (FROM table) as property_items.
I need to get result in this format:
=============================
id|description|products_count
=============================
1 |lorem ipsum|10
-----------------------------
2 |dolore sit |2
Thanks for any idea.
Try to use SELECT COUNT (DISTINCT products.id) as cnt
You can get the product ids that have all the properties by doing:
SELECT pp.property_id
FROM property_items pi INNER JOIN
product_properties pp
ON pi.id = pp.property_item_id INNER JOIN
products p
ON pp.product_id = p.id
WHERE pp.property_item_id IN ($ids)
GROUP BY pp.property_id
HAVING COUNT(DISTINCT pp.property_item_id) = $countIds -- has all of them
Note that I rationalized the joins. I think your simplification of the query wasn't quite right. I also added table aliases, so the query is easier to write and to read.
If you want the count of such products, use a subquery:
SELECT COUNT(*)
FROM (SELECT pp.property_id
FROM property_items pi INNER JOIN
product_properties pp
ON pi.id = pp.property_item_id INNER JOIN
products p
ON pp.product_id = p.id
WHERE find_in_set(pp.property_item_id, $ids)
GROUP BY pp.property_id
HAVING COUNT(DISTINCT pp.property_item_id) = $countIds -- has all of them
) ;
Your problem is probably because of this line:
WHERE pp.property_item_id IN ($ids)
If you are passing $ids as a comma-separated string, then your query will not work. Note the replacement above.

How to avoid Left join table show duplicate row?

I have some problem with the query issue when trying to sum up the quantity.
Table
This cart item table stored id_cart and id product
This order table stored id_cart and other id may be included such as supplier. This table is used to track order record and send notification to supplier.
Wrong result. Expected output = 1, 1, 1
SELECT id, id_product, SUM(qty)
from cart_item
left join Orderp using(id_cart)
group by id_product
http://sqlfiddle.com/#!9/07bf57/1
The issue caused by duplicate id_cart in order table as well. How can i handle this? Any solution to make it works? Thanks.
There is something wrong in your data, or in your data model
INSERT INTO OrderP(`id_order`,`id_cart`)VALUES(1, 1);
INSERT INTO OrderP(`id_order`,`id_cart`)VALUES(2, 1);
There are 2 rows for id_cart = 1, so the "natural join" will double every row when joining cart_item to orderp.
Using an inner join to a different column in orderp works better because now there is only one row in orederp for each cart_item.
SELECT id_product, sum(qty)
from cart_item ci
left join Orderp o on ci.id_cart = o.id_order
GROUP BY id_product
http://sqlfiddle.com/#!9/07bf57/13
Try the following query
SELECT
i.id_product,
p.name productname,
b.id_branch,
b.branchname,
SUM(i.qty)
from cart_item i
left join (SELECT DISTINCT id_cart,id_branch FROM Orderp) o on o.id_cart=i.id_cart
left join product p on i.id_product=p.id_product
left join catalog c on c.id_product=p.id_product and c.id_branch=o.id_branch
left join branch b on b.id_branch=o.id_branch
group by
i.id_product,
p.name,
b.id_branch,
b.branchname
The main problem in Orderp table because it containts two different orders for one cart (DISTINCT id_cart,id_branch helps here). And you need to use the second condition by id_branch for catalog (and c.id_branch=o.id_branch).
SQL Fiddle - http://sqlfiddle.com/#!9/f32d5f/16
And I think you can use everywhere INNER JOIN instead LEFT JOIN
SELECT
i.id_product,
p.name productname,
b.id_branch,
b.branchname,
SUM(i.qty)
from cart_item i
join (SELECT DISTINCT id_cart,id_branch FROM Orderp) o on o.id_cart=i.id_cart
join product p on i.id_product=p.id_product
join catalog c on c.id_product=p.id_product and c.id_branch=o.id_branch
join branch b on b.id_branch=o.id_branch
group by
i.id_product,
p.name,
b.id_branch,
b.branchname

MySQL JOIN tables with COUNT values

I have the following tables in my database.I only listed the important columns which can be used for joining.
I need to get the following output
Currently I'm using two seperate queries for each COUNT value
For assigned licenses
select
products.id,products.name,COUNT(assigned_licenses.id)
from
deployment_users
inner join
assigned_licenses
on
deployment_users.id = assigned_licenses.deployment_user_id
inner join
products
on
assigned_licenses.id = products.id
and
deployment_users.customer_id = 10
group by
assigned_licenses.id
;
For total licenses
select
products.id,products.name,COUNT(total_licenses.id)
from
customers
inner join
total_licenses
on
customers.iccode = licenses.iccode
inner join
products
on
total_licenses.id = products.id
and
customers.id = 10
group by
total_licenses.id
;
Since there are more than a 1,000 products that need to be listed,I want to combine them into a single query.How can I do that?
Your specification leaves some room for interpretation (e.g. can a user have assigned licenses without total licenses? if yes my query will fail.) but I would go with this.
SELECT
products.id,
products.name,
Count(Distinct total_licenses.id) As CountTotalLicenses,
Count(Distinct assigned_liceses.deployment_users_id) As CountAssignedLicenses
FROM products
LEFT JOIN total_licenses ON total_licenses.products_id = products.id
LEFT JOIN customers ON customers.iccode = total_licenses.customers_iccode
LEFT JOIN assigned_licenses ON assigned_liceses.total_licenses_id = total_licenses.id
WHERE
customers.id = 10
GROUP BY
products.id,
products.name
For the future it would be awesome if you could paste code as code and not as an image. People cannot simple copy paste snippets of your code and have to type everything again...
Try joining Both of your query
SELECT * FROM (
(First Query) as assigned_licn
INNER JOIN
(Second Query) as total_licn
USING (id)
);

sql join distinct php

I'm trying to create a list of my products. I got a join between two tables, products and products_photos.
I got X products which have one register on the products photos. The problem comes when I got two register on the product photos table which have the same id_product. Then, the results show 2 times the same product with the different photo. I want to show only the first one, not two times the same product.
SELECT DISTINCT p.*, photo.url_little
FROM ".Constants::$PRODUCTS_TABLE." as p
LEFT JOIN ".Constants::$PHOTOS_PRODUCTS_TABLE." as photo ON p.id=photo.id_product
WHERE p.id_client = ?
Probably I'm doing a bad use of the command distinct, but I don't know how to resolve this.
If you only want to show one, use a correlated subquery:
select p.*,
(select ph.url_little
from ".Constants::$PHOTOS_PRODUCTS_TABLE." ph
where p.id = ph.id_product
order by ph.id asc
limit 1
) as url_little
from ".Constants::$PRODUCTS_TABLE." as p
where p.id_client = ?;
if you use DISCINCT p.* then you obtain all the rows because you select also the row di (and this is unque)
try the same query but only with the column you need
SELECT DISTINCT p.column_i_need1, photo.url_little
FROM ".Constants::$PRODUCTS_TABLE." as p
LEFT JOIN ".Constants::$PHOTOS_PRODUCTS_TABLE." as photo
ON p.id = photo.id_product WHERE p.id_client = ?

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