Using cases to determine which table should join - mysql

I have four tables products, product_histories, vendor_invoices and invoices
This is the query I have developed
SELECT p.product_id, product_name, vendor_name FROM products AS p
INNER JOIN product_histories AS ph ON p.product_id = ph.product_id
CASE
WHEN ph.history_type = "P" THEN
LEFT JOIN vendor_invoices AS vi ON link_id = vi.vi_id
WHEN ph.history_type = "S" THEN
LEFT JOIN invoices AS i ON i.invoice_id = link_id
END
ORDER BY ph_id ASC
What I want that if ph.history_type is P then is should join vendor_invoices and if it is S then it should join invoices. But it says there is a syntax error.
Can anyone help me out with it? Or could show a better way to achieve this problem.

Related

subquery error in group by when converting from MySQL to PostgresSQL

I'm converting my database from MySQL to PostgresSQL, and I have this query which tries to sord the products by the cheapest price and the most popular in a given location. It works fine in MySQL, but in Postgres I'm running into problems with this query :
SELECT products.product_id,
suppliers.supplier_id,
product_code.desc_fa,
products.name_fa,
MIN(product_supplier.price) AS price,
SUM(COALESCE(orders.quantity, 0)) AS n_orders
FROM products
JOIN product_code ON product_code.code_id = products.code_id
JOIN product_supplier ON product_supplier.product_id = products.product_id
JOIN suppliers ON suppliers.supplier_id = product_supplier.supplier_id
JOIN product_tags ON product_tags.product_id = products.product_id
JOIN tags ON tags.tag_id = product_tags.tag_id
JOIN product_crop ON product_crop.product_id = products.product_id
JOIN crops ON crops.crops_id = product_crop.crop_id
LEFT JOIN orders
ON orders.product_id = products.product_id and orders.crop_id = product_crop.crop_id
LEFT JOIN user ON user.user_id = orders.user_id and user.location_id = 883
WHERE crops.crops_id = 1
AND product_supplier.quantity >= 3
AND tags.tag = 'علف کش'
GROUP BY products.name_fa
ORDER BY n_orders DESC
LIMIT 10;
It gives me this error :
column must appear in the GROUP BY clause or be used in an aggregate function
Any suggestions to how to work around this error ?
UPDATE :
According to the answers i was able to make it work by using this query:
WITH tem_1 AS (SELECT product_id, MIN(price) AS price FROM product_supplier GROUP BY product_id) ,
tem_2 AS (SELECT product_id, SUM(quantity) AS n_orders FROM orders Group by product_id)
SELECT products.product_id, suppliers.supplier_id, product_code.desc_fa, products.name_fa, tem_1.price,
products.telegraph, suppliers.location_id, COALESCE(tem_2.n_orders,0) AS quant FROM products
INNER JOIN product_supplier ON product_supplier.product_id = products.product_id
INNER JOIN suppliers ON suppliers.supplier_id = product_supplier.supplier_id
INNER JOIN product_code ON product_code.code_id = products.code_id
INNER JOIN product_crop ON product_crop.product_id = products.product_id
INNER JOIN crops ON crops.crops_id = product_crop.crop_id
INNER JOIN product_tags ON product_tags.product_id = products.product_id
INNER JOIN tags ON tags.tag_id = product_tags.tag_id
INNER JOIN tem_1 ON tem_1.price = product_supplier.price AND tem_1.product_id = products.product_id
LEFT JOIN tem_2 ON tem_2.product_id = products.product_id
WHERE crops.crops_id = 1 AND product_supplier.quantity >= 3 AND tags.tag = 'علف کش'
ORDER BY quant DESC
LIMIT 10;;
But since i'm fairly new to SQL, I wanted to know if my code is correct or is there a better way to implement it?
When you use aggregate function (as SUM, MIN and others) the other columns in your field list without aggregate function must be included in GROUP BY clause.
These fields:
products.product_id,
suppliers.supplier_id,
product_code.desc_fa,
products.name_fa
must be in GROUP BY.
Instead your GROUP BY clause has only the following field:
products.name_fa
You must add the other missing 3 fields
In MySql this error has turned off by default, so your query works fine, but in other DBMS you are in an error case.
You can see here how set MySql environment about the GROUP BY behaviour

How to get orders count sub-queries

I have some difficuties to get orders count with the following SQL query:
select
d.id,
d.title,
count(distinct o.id)
from store s
left join `order` o on o.store_id = s.id
left join order_product op on op.order_id=o.id
left join store_product sp on sp.id = op.product_id
left join product p on p.id = sp.product_id
left join department_category_to_entity dce1 on dce1.entity_type IN ('Product') and dce1.entity_id = p.id
left join department_category_to_entity dce2 on op.status != 'replaced' and
op.replacement_id is null and
dce2.entity_type IN ('StoreProduct') and
dce2.entity_id = sp.id
left join department_category_to_entity dce3 on op.status = 'replaced' and
op.replacement_id is not null and
dce3.entity_type IN ('StoreProduct') and
dce3.entity_id = op.replacement_id
left join department_category dc on dc.id = p.department_category_id or
dc.id = dce1.category_id or
dc.id = dce2.category_id or
dc.id = dce3.category_id
left join department d on d.id = dc.department_id
where d.id is not null
group by d.id;
Is it possible to get orders count without sub-queries or to get correct count of orders? Please, help... Thank you!
You have LEFT JOIN, which says to keep looking even if there is no row in the 'right' table. But, on the other hand, you are GROUPing BY a column in the last of a chain of LEFT JOINs! Perhaps you meant JOIN instead of LEFT JOIN??
Saying where d.id is not null is roughly equivalent to saying "Oops, all those LEFT JOINs could have been JOINs.
With GROUP BY and JOINs (LEFT or otherwise), you are doing an "inflate-deflate". What logically happens is all the JOINing is done to build a huge intermediate table with all the valid combinations. Then the COUNT(*) and GROUP BY are done. This tends to make the COUNTs (and SUMs, etc) have bigger values than expected.
What's the most direct route to get from department to order? It does not seem to involve store, so get rid of that table.
Are other tables irrelevant?
Even after addressing those issue, you still may be getting the wrong value. Please provide, for starters, `SHOW CREATE TABLE for each table.

mysql distinct query returning more than 1 result

I'm expecting for one product along with it's title and due amount. this query however is not efficient. Not sure with what i'm missing here. Any help would be appreciated
SELECT DISTINCT p.product_title, po.qty, co.due_amount
FROM pending_order po
LEFT JOIN products p ON p.product_id = po.product_id
LEFT JOIN customer_orders co ON po.invoice_no = co.invoice_no
LEFT JOIN customers cs ON cs.customer_id = co.customer_id
WHERE co.invoice_no = '1355021133'
the result i'm getting

MySQL query, dealing with active and inactive products

Facing a problem and not getting the hint for a few hours. Maybe onyone can help me out.
Have the following query which shows the Topsellers. So the status of the product (active or not) is saved in b.Article_Status (0=inactive, 1=active).
How do I get the products of the result list which have no active product in the productfamily at the moment. But the product shall still be shown if an old one was ordered (and so is in table order_items) is now inactive and the active one was not ordered yet.
Actual query looks as follow. Already fund a solution which works when the actual active product has been ordered once, but still the problem with the mentioned case.
SELECT count( a.order_itemid ) AS numOrders, c.Product_ID, c.Product_Name, d.producer_name
FROM order_items a
LEFT OUTER JOIN product_article b ON b.Article_ID = a.order_itemid
LEFT OUTER JOIN product c ON b.Article_Productid = c.Product_ID
LEFT OUTER JOIN producer d ON c.Product_Producer = d.producer_id
GROUP BY c.Product_ID
ORDER BY `numOrders` DESC
Solution was a WHERE EXISTS subquery
SELECT count( a.order_itemid ) AS numOrders, c.Product_ID, c.Product_Name, d.producer_name
FROM order_items a
LEFT OUTER JOIN product_article b ON b.Article_ID = a.order_itemid
LEFT OUTER JOIN product c ON b.Article_Productid = c.Product_ID
LEFT OUTER JOIN producer d ON c.Product_Producer = d.producer_id
WHERE EXISTS (SELECT * FROM product_article x WHERE c.Product_ID = x.Article_Productid AND x.Article_Status = 1)
GROUP BY c.Product_ID
ORDER BY `numOrders` DESC
LIMIT 5

COUNT(), GROUP BY and NULL Values in a MySql query

I have this MySql query working partially:
SELECT p.product_id, p.product_name, p.sales,
p.length, p.hits, COUNT(w.product_id) AS favorites
FROM `products` AS p, `products_mf_xref` AS m,
`wishlist_items` AS w
WHERE m.manufacturer_id = '1'
AND p.product_id = m.product_id
AND m.product_id = w.product_id
GROUP BY m.product_id ORDER BY p.product_id ASC
I'm recovering some fields from a table and trying to get the number of times these products are referenced in another table (this last table was called "whishlist"). The query is working OK, but I only get the products that are at least one time referenced in the wish list table.
I read that count(*) does not get NULL values what make sense, but I need also the products that are not referenced in the wish list table, I mean, products where COUNT(w.product_id) are equal to "0".
Any idea to recover all the products, including the null values?
Any idea to change my query? It's going to make me mad!!
Thanks in advance!
Use LEFT JOIN:
SELECT p.product_id, p.product_name, p.sales,
p.length, p.hits, COUNT(w.product_id) AS favorites
FROM `products` AS p
LEFT JOIN `products_mf_xref` AS m
ON p.product_id = m.product_id AND m.manufacturer_id = '1'
LEFT JOIN `wishlist_items` AS w ON m.product_id = w.product_id
GROUP BY m.product_id ORDER BY p.product_id ASC
By the way, as much as possible use JOIN to mirror the data relationships, use WHERE for filters