SQL joining two tables with a LEFTJOIN - mysql

I have tables
table_order
product_name
Below is the SQL I have to query table_order which works perfectly in outputting the product_id but I need it to show it's name and not number. I need to modify mySQL with a LEFTJOIN to somehow connect with table product_name but I keep getting an error. So instead of
99 = 15, 99 = 16
I need
99 = name1, 99 = name2
SELECT table_order.order_id, table_order.product_id
FROM table_order
WHERE table_order.order_id=99
ORDER BY table_order.order_product_id
table table_order
_________________________
order_id | product_id |
_________________________
99 | 15 |
99 | 16 |
_________________________
table product_name
___________________________
product_id | product_name |
___________________________
15 | name1 |
16 | name2 |
___________________________

Use
SELECT a.product_id, b.product_name
FROM table_order AS a LEFT JOIN product_name AS b ON a.product_id = b.product_id
WHERE a.order_id = '99'
ORDER BY a.product_id

You need to join the tables, as you say, on product_id.
SELECT table_order.order_id, product_name.product_name
FROM table_order
INNER JOIN product_name on table_order.product_id = product_name.product_id
WHERE table_order.order_id=99
ORDER BY table_order.product_id

Select t1.product_id,t2.product_name from table_order as t1
inner join(
select * from product_name
) as t2
on t1.product_id = t2.product_name
where t1.product_id = //some Number
See if that works.

If you need to output all the orders regardless of whether the product id of that table_order has a connection to product_table, you need to use LEFT JOIN.
SELECT o.order_id, p.product_name
FROM table_order o
LEFT JOIN product_name p ON o.product_id = p.product_id
ORDER BY o.product_id
However if you just need to get all the rows that exists in both tables, you can use an INNER JOIN
SELECT o.order_id, p.product_name
FROM table_order o
INNER JOIN product_name p ON o.product_id = p.product_id
ORDER BY o.product_id

Related

Why is SQL GROUP_CONCAT Query not working?

I have this query, but it gives me duplicate values in row
select products.name, products.image, products.image_second,
products.description, products.min_order, size_categories.size_id,
products.id,
GROUP_CONCAT( product_prices.price order by FIND_IN_SET(sizes.id, size_categories.size_id)) as price,
GROUP_CONCAT( sizes.name order by FIND_IN_SET(sizes.id, size_categories.size_id) ) as sizes_name,
units.name as units_name
from `products`
inner join `subcategories` on `products`.`subcategories_id` = `subcategories`.`id`
inner join `size_categories` on `subcategories`.`categories_id` = `size_categories`.`categories_id`
inner join `sizes` on FIND_IN_SET(sizes.id, size_categories.size_id) > '0'
inner join `units` on `units`.`id` = `products`.`units_id`
inner join product_prices on product_prices.products_id = products.id
where `products`.`id` = '1'
group by `products`.`name`, `products`.`image`,
`products`.`image_second`,
`products`.`description`, `products`.`min_order`,
`size_categories`.`size_id`, `products`.`id`
The result is like this
------ size_id | id | price | sizes_name
------ 1,2 1 43,32,43,32 2m,2m,3m,3m
32 is the price of 2m, and 43 is the price of 3m.
I need it in a single row and also i need to maintain the order (it should be like 32,43 and not like 43,32)
like
------ size_id | id | price | sizes_name
------ 1,2 1 32,43 2m,3m
Please Help
You missed the condition:
...and product_prices.size_id = sizes.id
when you join product_prices.
With this condition you don't need DISTINCT inside GROUP_CONCAT() for this sample data, although it may be needed for your actual data:
select products.name, size_categories.size_id, products.id,
GROUP_CONCAT(product_prices.price order by FIND_IN_SET(sizes.id, size_categories.size_id)) as price,
GROUP_CONCAT(sizes.name order by FIND_IN_SET(sizes.id, size_categories.size_id)) as sizes_name
from products
inner join subcategories on products.subcategories_id = subcategories.id
inner join size_categories on subcategories.categories_id = size_categories.categories_id
inner join sizes on FIND_IN_SET(sizes.id, size_categories.size_id)
inner join product_prices on product_prices.products_id = products.id and product_prices.size_id = sizes.id
where products.id = '1'
group by products.name, size_categories.size_id, products.id;
See the demo.
Results:
> name | size_id | id | price | sizes_name
> :--- | :------ | -: | :---- | :---------
> PR1 | 1,2 | 1 | 32,43 | 2m,3m

Fetch only matching records from two entities

Please help me with the MYSQL query.
Entity Name: OrderItem
Attributes: orderId(PK), orderItemSeqId(PK), productId
Entity Name: ProductFacility
Attributes: facilityId(PK), productId(PK), inventoryCount (Integer)
**OrderId | orderItemSeqId | productId**
OID1 | 0001 | 10000
OID1 | 0002 | 10001
OID1 | 0003 | 10002
**FacilityId | ProductId | InventoryCount**
FC_1 | 10000 | 12
FC_1 | 10001 | 5
FC_1 | 10002 | 7
FC_2 | 10001 | 1
FC_2 | 10002 | 6
FC_3 | 10002 | 7
Here I want to fetch the facility (FC_1) which has all the products available for order.
I don't want the facility records which has partial products (like facility FC_3 has only one (10002) product from order OID1)
I only want the facilityId records which have all the products from the order (ex OID1)
IMPORTANT POINT: This SQL will be executed on millions of records.
Try this:
select *
from ProductFacility f1
where (select count(distinct InventoryCount) cnt_fac
from ProductFacility f2
where f2.FacilityId = f1.FacilityId
and InventoryCount > 0
group by FacilityId ) = (select count(distinct productId)
from OrderItem );
Here is a DEMO
This will get you the facilities you are looking for
with cte as
(
select OrderId, count(*) as c
from orderT a
group by OrderId
)
select FacilityId, b.OrderId, count(*) as c from Facility a
inner join orderT b on a.ProductId = b.ProductId
group by FacilityId, b.OrderId
having count(*) = (select c from cte c where c.OrderId = b.OrderId)
To get a list of which facilities can satisfy an order, you need to check which facility has InventoryCount > 0 for each product in the order, which you can do with this query:
SELECT O.OrderId, F.FacilityID
FROM (SELECT DISTINCT productId
FROM OrderItem) P
CROSS JOIN (SELECT DISTINCT OrderId
FROM OrderItem) O
CROSS JOIN (SELECT DISTINCT FacilityId
FROM ProductFacility) F
LEFT JOIN OrderItem OI ON OI.OrderId = O.OrderID AND OI.productId = P.productId
LEFT JOIN ProductFacility PF ON PF.FacilityId = F.FacilityId AND PF.productId = OI.productId AND PF.InventoryCount > 0
GROUP BY O.OrderId, F.FacilityID
HAVING COUNT(OI.ProductId) = COUNT(PF.ProductId)
I have added an additional order to my demo which requires products 10001 and 10002; for that the output is
OrderId FacilityID
OID1 FC_1
OID2 FC_1
OID2 FC_2
Demo on SQLFiddle
This should work:
select oc.orderId, ofc.facilityId
from
(
select orderId, count(*) productCount
from OrderItem
group by orderId) oc
inner join
(
select pf.facilityId, oi.orderId, count(*) productsAvailableCount
from ProductFacility pf
inner join OrderItem oi on oi.productId = pf.productId and pf.inventoryCount > 0
group by pf.facilityId, oi.orderId
) ofc on ofc.orderId = oc.orderId and oc.productCount = ofc.productsAvailableCount
Demo on DB Fiddle

MySQL Queries with Meta Keys and Values

I have a hard time wrapping my head around coming up with a nice clean mysql query for this problem. I have two tables:
ORDER ITEMS ORDER ITEM META
----------------- ---------------------
ID Name ID Key Value
----------------- ---------------------
24 Product A 24 _qty 3
30 Product B 30 _qty 5
33 Product B 30 _weight 1000g
55 Product A 33 _qty 1
----------------- 33 _weight 500g
55 _qty 2
---------------------
I ran this query:
SELECT
oi.ID,
oi.Name,
oim1.Value as Qty,
oim2.Value as Weight
FROM
`order_items` as oi
INNER JOIN `order_item_meta` as oim1 ON oim1.ID = oi.ID
INNER JOIN `order_item_meta` as oim2 ON oim2.ID = oi.ID
WHERE
oim1.Key = '_qty' AND
oim2.Key = 'weight'
But it only gives me
-------------------------------
ID Name Qty Weight
-------------------------------
30 Product B 5 1000g
33 Product B 1 500g
-------------------------------
I need to include products that do not have _weight defined as a key so it will give me the following results:
-------------------------------
ID Name Qty Weight
-------------------------------
24 Product A 3
30 Product B 5 1000g
33 Product B 1 500g
55 Product A 2
-------------------------------
Try using an outer join:
select oi.id, oi.name, oim1.value as qty, oim2.value as weight
from order_items as oi
join order_item_meta as oim1
on oim1.id = oi.id
left join order_item_meta as oim2
on oim2.id = oi.id
and oim2.key = '_weight'
where oim1.key = '_qty'
Fiddle Test:
http://sqlfiddle.com/#!2/dd3ad6/2/0
If there is ever a situation where an order doesn't have a quantity you would also have to use an outer join for the quantity, like this:
select oi.id, oi.name, oim1.value as qty, oim2.value as weight
from order_items as oi
left join order_item_meta as oim1
on oim1.id = oi.id
and oim1.key = '_qty'
left join order_item_meta as oim2
on oim2.id = oi.id
and oim2.key = '_weight'
However if an order ALWAYS has an associated quantity (just not necessarily an associated weight) you should use the first query instead, an inner join for the quantity, and an outer join for the weight. (it all depends on your situation)

Join two table. One column using SUM

I need a little help with a MySQL query.
I have two tables one table is a list of product and one table is a list of warehouses quantity
product:
product_id product_name
1 name1
2 name2
3 name3
warehouse_product
id warehouse_id product_id product_quantity
1 1 1 15
2 2 1 30
3 1 2 100
4 2 2 30
5 1 3 20
6 2 3 40
The results Im looking to get from the above data would be
product_id product_name product_quantity
1 name1 45
2 name2 130
3 name3 60
I've tried many query but it's not working. My query is:
SELECT
product_id as product_id, SUM(quantity) as quantity
FROM
(SELECT
p.product_id as product_id, wp.product_quantity as quantity
FROM
product as p
LEFT JOIN warehouse_product as wp ON p.product_id = wp.product_id
WHERE
product_active = 1)
Try this:
SELECT p.product_id, p.product_name, SUM(wp.quantity) as quantity
FROM product as p
LEFT JOIN warehouse_product as wp
ON p.product_id = wp.product_id
AND product_active = 1
GROUP BY p.product_id, p.product_name
After JOINing the two tables you need to use GROUP BY so that SUM of quantity can be calculated for each product.
select p.product_id,p.product_name,sum(product_quantity) as 'product_quantity'
from product p inner join warehouse_product whp on
whp.product_id=p.product_id group by whp.product_id
select p.product_id, p.product_name,sum(w.product_quantity)
from
product p
inner join
warehouse_product w
on
p.product_id = w.product_id
group by w.product_id
order by p.product_name;
SELECT P.productid,
P.ProductName,
Sum(W.product_quantity) As quantity
FROM Product AS P
LEFT JOIN warehouse_product AS W
ON P.productid = W.productid
GROUP BY P.ProductId , P.ProductName
SQLFiddle

Union Two SQL Queries

I have a query like this
SELECT o.product_id,
p.name,
count(o.product_id) AS total_products_sold,
(SELECT count(o.id)
FROM ebay.`order` o) AS total_orders
FROM ebay.`order` o
INNER JOIN product p ON o.product_id = p.id
GROUP BY o.product_id
The total_orders is rerun when executed for each which not i want. I
Question:
I want the total_orders combines with every result set from the outer query.
I tried this but it only return 1 row
SELECT tps.product_id,
tps.name,
tps.total_products_sold,
count(oo.id) AS total_orders
FROM ebay.`order` oo
INNER JOIN
( SELECT o.id,
o.product_id,
p.name,
count(o.product_id) AS total_products_sold
FROM ebay.`order` o
INNER JOIN product p ON o.product_id = p.id
GROUP BY o.product_id ) AS tps ON oo.product_id = tps.product_id
Any better solution ?
Thanks.
You can use with rollup which will give you the total without changing the actual query
It wont give you the result in column of every row but you will get the result of total orders in the last row.
SELECT
o.product_id,
p.name,
count(distinct o.id) AS totalorder
FROM
ebay.`order` o
INNER JOIN
product p
ON
o.product_id = p.id
GROUP BY
o.product_id
WITH ROLLUP
For example
+-----------+------+------------+
| product_id| name | totalorder |
+-----------+------+------------+
| 2000 | A | 10 |
| 2001 | B | 20 |
| NULL | NULL | 30 | <--- Last row is having the Total order
+-----------+------+------------+
WITH ROLLUP
SELECT tps.product_id,
tps.name,
tps.total_products_sold,
s.total_orders
FROM ebay.`order` oo
INNER JOIN
(
SELECT o.id,
o.product_id,
p.name,
count(o.product_id) AS total_products_sold
FROM ebay.`order` o
INNER JOIN product p
ON o.product_id = p.id
GROUP BY o.product_id
) AS tps ON oo.product_id = tps.product_id
CROSS JOIN
(
SELECT count(id) total_orders
FROM ebay.`order`
) s