Sum price of a table with reference to two others - Mysql - mysql

I have these three tables and I want to get the sum of the price field of table 3 linked to table 1, table 2 being linked to table 1 and 3:
Table 1 - Tecnic
+--------------+------------+
| id_tecnic | name |
+--------------+------------+
| 1 | Michael |
| 2 | Billy |
| 3 | Joe |
+--------------+------------+
Table 2 - Linked
+--------------+------------+------------+
| id_linked | id_tecnic | id_mer |
+--------------+------------+------------+
| 1 | 1 | 4 |
| 2 | 3 | 1 |
| 3 | 3 | 2 |
+--------------+------------+------------+
Table 3 - Mer
+--------------+------------+
| id_mer | price |
+--------------+------------+
| 1 | 30 |
| 2 | 70 |
| 3 | 50 |
| 4 | 10 |
+--------------+------------+
Result
+--------------+------------+-------------+
| id_tecnic | name | total_price |
+--------------+------------+-------------+
| 1 | Michael | 10 |
| 2 | Billy | 0 |
| 3 | Joe | 90 |
+--------------+------------+-------------+
I have tried this:
SELECT te.id_tecnic,
SUM(m.price)
FROM tecnic te
LEFT JOIN linked l ON te.id_tecnic = l.id_tecnic
LEFT JOIN mer m ON l.id_mer = m.id_mer
GROUP BY te.id_tecnic

Billy doesn't have record in Table 2 - Linked so with purpose to have Billy in result set you have to start from table Table 3 - Mer, like:
SELECT te.id_tecnic, te.name, SUM(m.price)
FROM mer m
LEFT jOIN linked l ON l.id_mer = m.id_mer
LEFT JOIN te ON te.id_tecnic = l.id_tecnic
GROUP BY te.id_tecnic;

Related

Mysql, repeat row by the max count of details

I have two tables
Master table
|-----------|--------|------------|
| id_client | name | ci |
|-----------|--------|------------|
| 1 | B | 123 |
| 2 | A | 234 |
| 3 | C | 345 |
|-----------|--------|------------|
Detail of equipments
|-----------|--------------|
| id_client | id_equipment |
|-----------|--------------|
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
|-----------|--------------|
The result that I expected is:
All clientes with or without equipments
|-----------|----------------|----------------|
| id_client | id_equipment | numberEquipment|
|-----------|----------------|----------------|
| 1 | 1 | Equip1 |
| 1 | 2 | Equip2 |
| 2 | 3 | Equip1 |
| 2 | - | Equip2 |
| 3 | - | Equip1 |
| 3 | - | Equip2 |
|-----------|----------------|----------------|
Client 1 have two equipments and this is the max cant of equipments assigned, then, all clientes with minor than two have to fill the detail empty two times. client 2 have one equipment assigned, the second will be empty, and cliente 3 doesnt have any equipment, then the two equipments will be empty.
I was implemented crosstab on jasperreport, i have to define de columnGroup, when the name of group Equipment1, equipment2... etc, doesnt exist on any row this column group doesnt show.
I hope someone can helpme.
Thanks.
SELECT CONCAT('EQUIPMENT ',g.ennum) AS numberEquipment,
g.ID_CLIENTE as id_client, g.ID_EQUIPO as id_equipment,
(SELECT #running1:= 0) AS running1,(SELECT #previous1:= 0) AS previous1
FROM (
SELECT c.ID_CLIENTE, eq.ID_EQUIPO
#running1:=if(#previous1=concat(eq.ID_CLIENTE),#running1,0) + 1 as ennum, #previous1:=concat(eq.ID_CLIENTE)
FROM CLIENTE AS c
LEFT JOIN detail_equipments AS eq ON eq.ID_CLIENTE = c.ID_CLIENTE
ORDER BY c.ID_CLIENTE ) AS g
GROUP BY g.ID_CLIENTE, g.ID_EQUIPO
ORDER BY ID_CLIENTE, g.ennum
this show
|-----------|----------------|----------------|
| id_client | id_equipment | numberEquipment|
|-----------|----------------|----------------|
| 1 | 1 | Equip1 |
| 1 | 2 | Equip2 |
| 2 | 3 | Equip1 |
| 3 | - | Equip1 |
|-----------|----------------|----------------|

SQL: exact row match given certain elements

this is my first time posting here. I don't seem to find the answer to my problem.
So... I'm arranging a DB for a school project, a cookbook that only shows recipes that can be made with existing elements from the "shelf".
These ingredients have to have an exact ingredients match.
user:
+---------------+------+----------+----------+
| email | name | lastname | password |
+---------------+------+----------+----------+
| pal#mail.com | John | Potato | password |
| they#mail.com | Mary | Carrot | password |
+---------------+------+----------+----------+
shelf:
+---------+------------+---------------+
| shelfID | ingredient | user |
+---------+------------+---------------+
| 1 | 1 | pal#mail.com |
| 2 | 2 | pal#mail.com |
| 3 | 3 | pal#mail.com |
| 4 | 4 | pal#mail.com |
| 5 | 10 | they#mail.com |
| 6 | 12 | they#mail.com |
+---------+------------+---------------+
This is my recipe_ingredient relationship table
recipe_ingredient:
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
| 1 | 10 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 2 |
| 3 | 3 |
| 3 | 15 |
+--------+------------+
I've tried this query:
SELECT
rec_ing.recipe, shf.ingredient, shf.user
FROM
recipes_ingredients AS rec_ing
INNER JOIN
shelf AS shf ON rec_ing.ingredient = shf.ingredient
INNER JOIN
users AS usr ON shf.user = usr.email
WHERE
usr.email = 'pal#mail.com'
that returns this table:
+--------+------------+--------------+
| recipe | ingredient | user |
+--------+------------+--------------+
| 1 | 1 | pal#mail.com |
| 1 | 2 | pal#mail.com |
| 1 | 4 | pal#mail.com |
| 2 | 1 | pal#mail.com |
| 2 | 2 | pal#mail.com |
| 2 | 3 | pal#mail.com |
| 2 | 4 | pal#mail.com |
| 3 | 2 | pal#mail.com |
| 3 | 3 | pal#mail.com |
+--------+------------+--------------+
Although it's true that the Recipe 1 contains ingredients from my shelf, it's also missing Ingredient 10
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
| 1 | 10 |
| ... | ... |
+--------+------------+
I'm trying to only get this kind of result set.
+--------+------------+
| recipe | ingredient |
+--------+------------+
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 4 |
+--------+------------+
Because Recipe 2 contains all elements from my shelf
I have been going around all day with this problem ... What could be missing?
This is a bit tricky, because you need to aggregate your current query by recipe, but you also need the original query to get back the full records. Sadly, MySQL does not support common table exprrssions or other features which could give us a less verbose query.
SELECT
rec_ing.recipe,
shf.ingredient,
shf.user
FROM recipes_ingredients AS rec_ing
INNER JOIN shelf AS shf
ON rec_ing.ingredient = shf.ingredient
INNER JOIN users AS usr
ON shf.user = usr.email
INNER JOIN
(
SELECT rec_ing.recipe
FROM recipes_ingredients AS rec_ing
INNER JOIN shelf AS shf
ON rec_ing.ingredient = shf.ingredient
LEFT JOIN users AS usr
ON shf.user = usr.email
WHERE
usr.email = 'pal#mail.com'
GROUP BY rec_ing.recipe
HAVING COUNT(usr.email) = COUNT(*)
) t
ON rec_ing.recipe = t.recipe
WHERE
usr.email = 'pal#mail.com'
The basic strategy here is to just do one additional join to a subquery which identifies all recipes where every ingredient belongs to a given user. The critical part is the following:
HAVING COUNT(usr.email) = COUNT(*)
This checks that the total number of rows for a given recipe matches the number of rows which have been assigned to a given user.

How to SELECT 2 tbls but only 1 row from second tbl with lowest PK in MySQL?

structure:
tbl 1
|car_id(PK)| make | model | year |
-----------------------------------
| 1 | Toyot | Camry | 1999 |
| 2 | Honda | Civic | 2005 |
tbl 2
|img_id(PK)| car_id| img_link |
------------------------------------
| 1 | 1 | tcamry1.jpeg |
| 2 | 1 | tcamry2.jpeg |
| 3 | 1 | tcamry3.jpeg |
| 4 | 2 | hcivic1.jpeg |
| 5 | 2 | hcivic2.jpeg |
My query:
SELECT *
FROM cars c
LEFT JOIN imgs g
ON c.car_id=g.car_id
WHERE 1
Result:
|img_id(PK)| car_id| make | model | year | img_link |
-----------------------------------------------------------
| 1 | 1 | Toyot | Camry | 1999 | tcamry1.jpeg |
| 2 | 1 | Toyot | Camry | 1999 | tcamry2.jpeg |
| 3 | 1 | Toyot | Camry | 1999 | tcamry3.jpeg |
| 4 | 2 | Honda | Civic | 2005 | hcivic1.jpeg |
| 5 | 2 | Honda | Civic | 2005 | hcivic2.jpeg |
I need to get 1 row for each car and have WHERE clause with something like lowest img_id value out of all img_id related to the same car.
Result I want:
|img_id(PK)| car_id| make | model | year | img_link |
-----------------------------------------------------------
| 1 | 1 | Toyot | Camry | 1999 | tcamry1.jpeg |
| 4 | 2 | Honda | Civic | 2005 | hcivic1.jpeg |
Thank you.
UPDATE:
I need something along these lines :-/
SELECT g.id, c.car_id, c.mc_make, c.mc_model, c.mc_year, c.mc_desc
FROM mycars c
INNER JOIN (SELECT * FROM mycars_gallery g WHERE )
ON c.car_id=g.car_id
WHERE g.id = min(g.id)
Try:
SELECT MIN(b.img_id), a.car_id, a.make, a.model, a.year, b.img_link
FROM cars a
LEFT JOIN imgs b ON a.car_id = b.car_id
GROUP BY a.car_id, a.make, a.model, a.year ;
Demo: http://sqlfiddle.com/#!2/1469f/15
Hope this helps.
SELECT *
FROM cars c
LEFT JOIN imgs g
ON c.car_id=g.car_id
WHERE img_id IN(SELECT MIN(img_id)) GROUP BY model
SELECT *
FROM cars c
LEFT JOIN imgs g
ON c.car_id=g.car_id
WHERE 1
GROUP BY g.img_link;
try this.. not sure though.

Update data in Multiple table

Three table as follow
mysql> select * from food;
+--------+------+-------+
| foodid | name | price |
+--------+------+-------+
| 1 | 雞 | 100 |
| 2 | 鴨 | 200 |
| 3 | 魚 | 300 |
| 4 | 肉 | 400 |
+--------+------+-------+
4 rows in set
mysql> select * from drink;
+---------+------+-------+
| drinkid | name | price |
+---------+------+-------+
| 1 | 紅茶 | 50 |
| 2 | 綠茶 | 100 |
| 3 | 奶茶 | 150 |
+---------+------+-------+
3 rows in set
mysql> select * from order_table;
+----+-----------+--------+---------+------------+-------------+-------------+
| id | user_name | foodid | drinkid | food_count | drink_count | total_price |
+----+-----------+--------+---------+------------+-------------+-------------+
| 2 | 小明 | 3 | 2 | 2 | 2 | 0 |
| 3 | 小華 | 1 | 1 | 1 | 8 | 0 |
| 4 | 小英 | 1 | 3 | 3 | 3 | 0 |
| 6 | 小a | 2 | 1 | 4 | 6 | 0 |
| 7 | 小b | 2 | 2 | 5 | 4 | 0 |
| 8 | 小c | 2 | 3 | 6 | 10 | 0 |
| 9 | 大A | 3 | 1 | 9 | 8 | 0 |
| 10 | 大B | 3 | 2 | 5 | 4 | 0 |
| 11 | 大C | 3 | 3 | 10 | 3 | 0 |
+----+-----------+--------+---------+------------+-------------+-------------+
foodid in order_table is link to foodid in food table,
drinkid in order_table is link to drinkid in drink table,
Now, I want to calculate total price,
Total_price =
order_table.foodid(food.price in food table) * order_table.food_count +
order_table.drinkid(drink.price in drink table) * order_table.drink_count;
So, let me knowlege the command to update total price
thx a lot.
The reason why I used LEFT JOIN on the following query is because I assumed that some orders may only contain drinks or foods.
UPDATE order_table a
LEFT JOIN food b
ON a.foodid = b.foodID
LEFT JOIN drink c
ON a.drinkID = c.drinkID
SET a.total_price = (a.food_count * COALESCE(b.price, 0) +
a.drink_count * COALESCE(c.price, 0))
SQLFiddle Demo
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Something like this should be close:
SELECT COALESCE(F.Price,0)*OT.Food_Count+COALESCE(D.Price,0)*OT.Drink_Count Total_price
FROM Order_Table OT
LEFT JOIN Food F ON OT.FoodId = F.FoodId
LEFT JOIN Drink D ON OT.DrinkId = D.DrinkId
And to actually update that column:
UPDATE Order_Table OT
LEFT JOIN Food F ON OT.FoodId = F.FoodId
LEFT JOIN Drink D ON OT.DrinkId = D.DrinkId
SET OT.Total_Price = COALESCE(F.Price,0)*OT.Food_Count+COALESCE(D.Price,0)*OT.Drink_Count

How should I write this MySQL query containing multiple Left Joins

I have a query consisting of multiple joins and I am wondering whether it can be re-written to improve performance.
I have 2 tables as follows (I have removed non-important columns for this example):
slots
------------------------------------------
| id | name | slot_1 | slot_2 | slot_3 |
------------------------------------------
| 1 | Bob | 1 | 2 | 3 |
| 2 | Jim | 4 | 3 | 3 |
| 3 | Alf | 1 | 2 | 5 |
------------------------------------------
(There are 25 slots in total, each in it's own column)
slot_details
-----------------------------------
| id | stat_1 | stat_2 | stat_3 |
-----------------------------------
| 1 | 1 | 5 | 6 |
| 2 | 4 | 31 | 23 |
| 3 | 6 | 5 | 7 |
| 4 | 7 | 4 | 9 |
| 5 | 2 | 3 | 5 |
-----------------------------------
(There are 10 stats in total)
The query is as follows:
SELECT
slots.name,
slot_1_details.stat_1 AS slot_1_stat_1,
slot_1_details.stat_2 AS slot_1_stat_2,
slot_1_details.stat_3 AS slot_1_stat_3,
slot_2_details.stat_1 AS slot_2_stat_1,
slot_2_details.stat_2 AS slot_2_stat_2,
slot_2_details.stat_3 AS slot_2_stat_3,
slot_3_details.stat_1 AS slot_3_stat_1,
slot_3_details.stat_2 AS slot_3_stat_2,
slot_3_details.stat_3 AS slot_3_stat_3
FROM
slots
LEFT JOIN
slot_details AS slot_1_details
ON (
slot_1_details.id = slots.slot_1
)
LEFT JOIN
slot_details AS slot_2_details
ON (
slot_2_details.id = slots.slot_2
)
LEFT JOIN
slot_details AS slot_3_details
ON (
slot_3_details.id = slots.slot_3
)
WHERE (
slots.id = 1
)
The expected outcome of this query would be as follows:
| name | slot_1_stat_1 | slot_1_stat_2 | slot_1_stat_3 | slot_2_stat_1 | slot_2_stat_2 | slot_2_stat_3 | slot_3_stat_1 | slot_3_stat_2 | slot_3_stat_3 |
|bob | 1 | 5 | 6 | 4 | 31 | 23 | 6 | 5 | 7 |
Unfortunately I am not in a situation where I can change the tables.
Thank you for the help!
maybe
SELECT * FROM slots s LEFT JOIN slot_details sd ON s.id=sd.id
but i'm not sure because the query you posted is very confusing.
what are the keys of those tables?