Retrieve the duplicate data without group from subquery - mysql

i have tables below
catalog_product_entity
entity_id
sku
type
1
1-1669197697
bundle
2
skua
single
3
skub
single
4
skuc
single
catalog_product_bundle_selection
parent_product_id
product_id
1
2
1
3
1
4
promotion
sku
1-1669197697
product_shipping
product_id
code
2
jne
2
jnt
3
jne
3
jnt
4
jne
4
jnt
and the sample queries
SELECT e.*, COUNT(DISTINCT bundle.product_id) AS children FROM catalog_product_entity AS e
INNER JOIN product_promotion AS promotion ON promotion.sku = e.sku
INNER JOIN catalog_product_bundle_selection AS bundle ON bundle.parent_product_id = e.entity_id
INNER JOIN product_shipping AS shipping ON shipping.product_id = bundle.product_id
INNER JOIN (
SELECT COUNT(DISTINCT bundle.product_id) AS total_item, product.sku
FROM catalog_product_bundle_selection AS bundle
INNER JOIN catalog_product_entity AS product ON product.entity_id = bundle.parent_product_id
INNER JOIN product_promotion AS promotion ON promotion.sku = product.sku
GROUP BY product.sku
) AS summary ON summary.sku = e.sku
GROUP BY e.entity_id, shipping.code, summary.total_item
HAVING COUNT(DISTINCT bundle.product_id) = summary.total_item
and the result is
There is a bundle with 3 items that have different shipping, but same as the others. The point is i want to get the data bundle with condition if the items have at least one or more similar shipping.
how can i retrieve only one record without put the above query inside subquery and group it by parent, anyone can help?

Related

MYSQL - Query to get values from one table if the value doesn't exist in another table

I'm struggling with a query. I need to create a view based on this query.
I've got 3 tables: seller, item, seller_item
Seller table
name
id
S1
1
S2
2
S3
3
Item table
name
id
price
I1
1
50
I2
2
100
Seller_Item table
seller_id
item_id
price
1
1
75
2
1
25
View I'd like to obtain
nome
item
price
S1
I1
75
S1
I2
100
S2
I1
25
S2
I2
100
S3
I1
50
S3
I2
100
Basically, if the item is not present in the table seller_item I want to insert the default value coming from the item table otherwise the one from the seller_item table.
I was able to achieve something similar using WHERE NOT EXIST, but only when I ask for a specific seller id, instead, here, I want to have the list of all the sellers with all items.
Thank you.
----- SOLUTION -----
Thank you for your quick answers.
Just few minutes after I posted the question I found the solution. It was a lot more verbose than what I was able to find thanks your suggestions.
The final query (with all the values I need) is this one:
SELECT
S.name AS name,
I.name AS item,
IF(SI.visible = 0, SI.visible, I.visible) AS visible,
IF(COALESCE(SI.price, 0) = 0, I.price, SI.price) AS price FROM seller S JOIN item I LEFT JOIN seller_item SI ON S.id = SI.seller_id AND I.id = SI.item_id ORDER BY 1, 2
Thank you again!
You can use CROSS JOIN and COALESCE function.
The query is as follows:
SELECT
s.name nome, i.name item, COALESCE(si.price, i.price) price
FROM
Seller s CROSS JOIN Item i
LEFT OUTER JOIN Seller_Item si
ON s.id=seller_id AND i.id=item_id
ORDER BY 1, 2
Fiddle
You could try using a corrso join for get all the combination between item and seler and the join the seller:iem ..
when the join match use the seller price otherwise use the imte price
select seller.name
, item.name
case when seller_item.item_id is null then item.price else seller_item.price
from seeler
cross join item
left join seller_item on seller_item.item_id = item.id
Hope the below query is what you are looking for
SELECT
s.name as name,
i.name as item,
IFNULL(si.price, i.price) as price
FROM item i
LEFT JOIN seller_item si ON i.id = si.item_id
LEFT JOIN seller s ON s.id = si.seller_id

"INNER JOIN" and "LEFT JOIN" with "GROUP BY"

My tables looks like this
sales
----------------------------------------------------------
id ordernumber quantity category_id price
1 402-9182243-8008368 1 3 22.95
2 406-3666671-8627555 2 3 6.95
3 303-1935495-5532309 1 1 7.95
4 171-5799800-1198702 1 2 159.95
5 403-2398078-4901169 2 2 18.95
category
--------------
id name
1 bikes
2 shoes
3 planes
returns
--------------
id ordernumber quantity costs
1 402-9182243-8008368 1 22.95
2 402-9182243-8008368 5.95 // return shipping fee
And here is my query
SELECT c.name,
SUM(v.quantity) AS sold, # wrong
SUM(s.quantity * s.price) AS turnover, # wrong
SUM(r.costs) AS returncosts,
FROM sales AS s
INNER JOIN categories AS c ON c.id = s.category_id
LEFT JOIN returns AS r ON r.ordernumber = s.ordernumber
GROUP BY c.name
I have some inner joins with aggregate functions.
But I also need "return" with a "Left Join" (I think).
And with Left Join, my aggregate functions dont work anymore.
Left Join adds additional rows. Additional data, for sum().
I need a single query, so every column is sortable later.
I would be happy about any help. Best Regards
It's a semi cartesian product because ordernumber is not unique in returns table.
We can see what's happening if we remove the aggregate functions and return the detail rows.
One possible approach is to pre-aggregate returns in an inline view, so that unique values of ordernumber are returned.
Assuming ordernumber is unique in sales table, then something like this:
SELECT c.name
, SUM(s.quantity) AS sold
, SUM(s.quantity * s.price) AS turnover
, SUM(r.returncosts) AS returncosts
FROM sales s
JOIN categories c
ON c.id = s.category_id
LEFT
JOIN ( SELECT t.ordernumber
, SUM(t.costs) AS returncosts
FROM returns t
GROUP
BY t.ordernumber
) r
ON r.ordernumber = s.ordernumber
GROUP
BY c.name
You can sum the quantity separately from the LEFT JOIN in a sub query as follows:
SELECT t1.name, t1.sold, t1.turnover, SUM(r.costs) AS returncosts
FROM(
SELECT c.name,
SUM(s.quantity) AS sold,
SUM(s.quantity * s.price) AS turnover
FROM sales AS s
INNER JOIN categories AS c ON c.id = s.category_id
GROUP BY name
) t1
LEFT JOIN returns AS r ON r.ordernumber = s.ordernumber
GROUP BY t1.name, t1.sold, t1.turnover

how to get result of join also for records that dont have a joined record with another table?

I have this query:
SELECT suppliers.id, count(*)
FROM suppliers
INNER JOIN supplier_addresses
ON suppliers.id = supplier_addresses.supplier_id
GROUP BY suppliers.id;
this gives my a table of supplierId and count of its addresses in the supplier_addresses table. But it only shows me suppliers that have at least 1 address.
I want to see in the result also count of 0 addresses...for example:
supplier.id | count(*)
1 3
2 0
3 1
4 9
in my query I dont see the second record.
Use LEFT JOIN
SELECT suppliers.id, count(supplier_addresses.supplier_id )
FROM suppliers
LEFT JOIN supplier_addresses
ON suppliers.id = supplier_addresses.supplier_id
GROUP BY suppliers.id;

Joing multiple with one master table

I have six tables- Project,Equipment,Fish,Staff and the junction tables - Project_Equipment,Project_Fish and Project_Staff.I want to retrieve Project total cost.
So, I wrote the statement like follows,
SELECT P.ProjectID, (SUM(E.EquipPrice*PE.EQuantity)+SUM(F.FishPrice*PF.FQuantity)+SUM(PS.Salary)) as ProjectCost
FROM Equipment as E INNER JOIN Project_Equipment as PE
ON E.EquipID=PE.EquipID
INNER JOIN Project as P
ON PE.ProjectID=P.ProjectID
INNER JOIN Project_Fish as PF
ON P.ProjectID=PF.ProjectID
INNER JOIN Fish as F
ON PF.FishID=F.FishID
INNER JOIN Project_Staff as PS
ON P.ProjectID=PS.ProjectID
INNER JOIN Staff as S
PS.StaffID=S.StaffID
GROUP BY ProjectID
But, I got the price with twice of correct amount.
Your query will end up with a lot of duplicate results. Consider the following simpler case:
Table: Project
ProjectID EQuantity
1 1
2 1
Table: Equipment
EquipID EPrice
1 1
2 1
Table: Fish
FishID
1
2
Table: Project_Equipment
ProjectID EquipID
1 1
1 2
2 1
2 2
Table: Project_Fish
ProjectID FishID
1 1
1 2
2 1
2 2
Now, let's look at the results of a Project_Equipment query only:
SELECT p.projectid, e.eprice, pe.equantity FROM project p
INNER JOIN project_equipment pe ON pe.projectid=p.projectid
INNER JOIN equipment e ON e.equipid=pe.equipid
ProjectID EPrice EQuantity
1 1 1 // a
1 1 1 // b
2 1 1 // c
2 1 1 // d
That's as expected; a list of the price and quantity of each piece of equipment used by each project. But what do you think will happen when we INNER JOIN that to project_fish? That first result has project 1 in it twice, and project 2 in it twice, so we end up with every combination of that result and project_fish!
SELECT p.projectid, e.eprice, pe.equantity, f.fishid FROM project p
INNER JOIN project_equipment pe ON pe.projectid=p.projectid
INNER JOIN equipment e ON e.equipid=pe.equipid
INNER JOIN project_fish pf ON pf.projectid=p.projectid
ProjectID EPrice EQuantity FishID
1 1 1 1 // from a above
1 1 1 2 // from a above
1 1 1 1 // from b above
1 1 1 2 // from b above
2 1 1 1 // from c above
2 1 1 2 // from c above
2 1 1 1 // from d above
2 1 1 2 // from d above
This duplication will continue with every inner join. The amount your price will be off won't always be 2x, it will actually depend on the number of combinations of all your joins.
So, you can't really do what you are trying to do with this particular query. Instead you'll have to calculate the cost of each relationship separately. Then you sum all those together. You can do this by selecting each one separately and calculating the cost into a ProjectID and ProjectCost column, using UNION to concatenate those altogether, then once again grouping the results by ProjectID and summing the individual ProjectCost subtotals.
I explained that poorly, but think of it as subtotaling equipment, fish, and salary costs, then sticking all those subtotals into one table and summing that. E.g.:
SELECT x.projectid, SUM(x.ProjectCost) FROM
(
SELECT p.projectid, SUM(e.eprice * pe.equantity) ProjectCost FROM project p
INNER JOIN project_equipment pe ON pe.projectid=p.projectid
INNER JOIN equipment e ON e.equipid=pe.equipid
GROUP BY p.projectid
UNION
SELECT p.projectid, SUM(f.fprice * pf.fquantity) ProjectCost FROM project p
INNER JOIN project_fish pf ON pf.projectid=p.projectid
INNER JOIN fish f ON f.fishid=pf.fishid
GROUP BY p.projectid
UNION
SELECT p.projectid, SUM(s.salary) ProjectCost FROM project p
INNER JOIN project_staff ps ON ps.staffid=p.projectid
INNER JOIN staff s ON s.staffid=ps.staffid
GROUP BY p.projectid
) x
GROUP BY x.projectid
Each of the subqueries produces a projectid column and a ProjectCost column. Run the subquery (between the parens) by itself to see the results. The outer query then adds the subtotals for the projects.
Sorry, btw, I renamed your EquipPrice and FishPrice columns to EPrice and FPrice when I was testing.

Selecting rows from multiple tables. How?

Let's say that we have tree tables.
Products Fields Fields Value
---------------- ------------- --------------
pid catid fid catid fid pid value
-------|-------| -----|------- ------|-----|--------
1 1 1 1 1 1 25%
2 1 2 1 1 2 32.5%
3 2 2 1 45%
2 2 42%
3 1 17.3%
3 2 21%
The normal way is selecting Products in a one query and loop through result set(RS1).
Then we select Fields for catid per each row (RS2).
Then doing the same action with RS2 for selecting `Fields Value'.
Only problem is performance issue that will be reduced due to executing a lot of queries` when there are a lot of rows in each table.
Would you suggest me better solution to execute less queries ?
edit
I want to show each product in a box and show fields for each product with it's proper value. joining tree tables together will returns duplicated values for each FieldValue in Products and not usable in loop.
Guessing what you need, try this:
SELECT f.catid, fv.* FROM Fields f
INNER JOIN Products p
ON f.catid = p.catid
INNER JOIN FieldsValue fv
ON fv.fid = f.fid AND fv.pid = p.pid
SELECT *
FROM Products
NATURAL JOIN Fields
NATURAL JOIN FieldsValue;
use Join Syntax :
SELECT * FROM Products as P
LEFT JOIN FieldsValue as FV ON FV.PID = P.PID
LEFT JOIN Fields as F on F.fid = FV.fid
You can join the tables together using left join:
select *
from Products p
left join Fields f on f.catid = p.catid
left join `fields value` fv on fv.fid = f.fid on fv.pid = p.pid
where p.pid = 1