Subtract count from left join and inner join in SQL - mysql

I want to merge two tables and subtract the number of orders in resulting table from left join from the resulting table in inner join.
This is what I have done but I do not know if this is correct or how to proceed?
WITH t1 AS (
SELECT *
FROM orders
LEFT JOIN food ON orders.id = food.id
),
t2 AS (
SELECT *
FROM orders
INNER JOIN food ON orders.id = food.id
)
SELECT
/* now what? */
Now I want to subtract number of rows in two tables.
I do not know how to proceed, should I join tables again and do subtraction, is there an easier way?

You don't even need two separate queries to answer your question. The only difference in result set between the left and inner joins is that the former will retain order records which do not map. So, you may simply write:
-- query #3
SELECT *
FROM orders o
LEFT JOIN food f
ON f.id = o.id
WHERE f.id IS NULL;
If you combine the result set from above with the inner join query #2, you will get the total left join query #1 result set without the WHERE clause.
So count(query #1) = count(query #2) + count(query #3)

Related

ON clause in SQL join-does order matter?

Are these two same?
- SELECT p.name,o.order_time FROM ORDERS o INNER JOIN PRODUCTS p on **o.product_id=p.id**;
- SELECT p.name,o.order_time FROM ORDERS o INNER JOIN PRODUCTS p on **p.id=o.product_id**;
And are these two the same thing:
- SELECT p.name,o.order_time FROM ORDERS o LEFT JOIN PRODUCTS p on **o.product_id=p.id;**
- SELECT p.name,o.order_time FROM ORDERS o LEFT JOIN PRODUCTS p on **p.id=o.product_id;**
Yes, first 2 queries are exactly same in terms of performance and result. In addition to that, first 2 queries is same as below query,
SELECT p.name,o.order_time FROM PRODUCTS p INNER JOIN ORDERS o on p.id=o.product_id;
Which in turn is same as,
SELECT p.name,o.order_time FROM PRODUCTS p INNER JOIN ORDERS o on o.product_id=p.id;
Note: the order of inner join tables is swapped as well.
3rd and 4th are same as well in terms of performance and result. You can't swap the order of table here, unless dataset guarantees same result.
Based on the dataset, first 2 queries can yield same or different result than last 2 queries.
Reason is = is commutative, it means a=b is same as b=a. Extending it further, just INNER JOIN is also commutative.

Need to join MySql query to 3 tables

SELECT products.acctnum,products.subacctnum,NOW(),
items.amount,items.id,items.invoice_id,items.product_id,
items.po_id, invoices.customer_id, purchaseorders.vendor_id FROM items
INNER JOIN (products, invoices, purchaseorders)
ON (items.product_id=products.product_id AND items.invoice_id=invoices.id
AND items.po_id=purchaseorders.id)
This returns nothing... however..
SELECT products.acctnum,products.subacctnum,NOW(),
items.amount,items.id,items.invoice_id,items.product_id,
items.po_id, purchaseorders.vendor_id FROM items
INNER JOIN (products, purchaseorders)
ON (products.product_id=items.product_id AND purchaseorders.id=items.po_id)
Works...
SELECT products.acctnum,products.subacctnum,NOW(),
items.amount,items.id,items.invoice_id,items.product_id,
items.po_id, invoices.customer_id FROM items
INNER JOIN (products, invoices)
ON (products.product_id=items.product_id AND invoices.id=items.invoice_id)
Works...
Works for the rows I need in the result but when I join the 3rd table it doesn't work. LEFT JOIN displayed all the columns I needed but some rows were NULL.
I imagine the join clause you want looks more like this:
FROM items LEFT JOIN
invoices
ON invoices.id = items.invoice_id LEFT JOIN
purchaseorders
ON purchaseorders.id = items.po_id LEFT JOIN
products
ON products.product_id = items.product_id
I'm not sure which fields are not valid when you select them, but you can probably fix such issues by using coalesce() with appropriate fields from invoices and purchaseorders.

SQL Query, subquery minus subquery?

Ok, so Ive been trying to get this query working for hours now, but nothing I seem to do will get me the results I am after.
SELECT COALESCE(SUM(ps.cost), 0) AS ps_total
FROM Customers c
LEFT JOIN ProductSales ps ON c.customer_ID = ps.customer_ID
GROUP BY c.sex;
SELECT COALESCE(SUM(hc.cost), 0) AS hc_total
FROM Customers c
LEFT JOIN HairCuts hc ON c.customer_ID = hc.customer_ID
GROUP BY c.sex;
So the above two queries work fine. Each one finds the total spent on either products or hair cuts and groups by gener thus giving me the total spent on cuts and products for males and females individually.However somehow I need to combine these in such a way that I can display the gender(s) that spent more on products than on haircuts.
Any help with this would be very much appreciated.
P.S hopefully the question is clear enough. If not Ill try to elaborate.
Another way you can join your both query results as
SELECT t1.sex,
COALESCE(t1.ps_total - t2.hc_total,0) AS `difference`
FROM
(SELECT COALESCE(SUM(ps.cost), 0) AS ps_total ,c.sex
FROM Customers c
LEFT JOIN ProductSales ps ON c.customer_ID = ps.customer_ID
GROUP BY c.sex) t1
LEFT JOIN
(SELECT COALESCE(SUM(hc.cost), 0) AS hc_total ,c.sex
FROM Customers c
LEFT JOIN HairCuts hc ON c.customer_ID = hc.customer_ID
GROUP BY c.sex) t2
USING(sex)
HAVING difference > 0
Edit from comments
I have used a short syntax for ON() clause like USING(sex) = ON(t1.sex=t2.sex) if you have a same name for a column in both tables you can use USING() if you have different then you need to use ON() syntax
Like
Table1 column(category_id primary key,...)
Table2 column(category_id foreign key,...)
Then you can easily use USING()
SELECT * FROM
Table1
JOIN Table2
USING(category_id )
But if you have different name for association then you need to use ON() clause

Left outer join to a generated table?

Am I on completely the wrong tack ?
I want to do a left outer join to a query generated from 2 tables , but i keep getting errors. Do I need a different approach?
t1:
ID, Surname,Firstname
t2:
ID,JobNo,Confirmed
I have the following query:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
I want to add:
LEFT OUTER JOIN contacted (ON t1.StaffID=contact.ID AND t2.JobNo=contact.JobNo)"
Can I do a left outer join to a query generated from 2 tables ?
In order to use the t1 and t2 in the left outer join that you want to add you need to join them with the first tables, you can't reference them directly in the left outer join you, Something like the following:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
Inner join t1 on ...
Inner join t2 on ...
LEFT OUTER JOIN contacted c
on t1.StaffID=c.ID AND t2.JobNo = c.JobNo
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
So, based in your tables' structure, define the conditions of the two joins with t1 and t2 with other tables.
Here is the an example of a left join to a sub query. This might be what you are looking for.
select
parts.id,
min(inv2.id) as nextFIFOitemid
from test.parts
left join
( select
inventory.id,
coalesce(parts.id, 1) as partid
from test.inventory
left join test.parts
on (parts.id = inventory.partid)
) inv2
on (parts.id = inv2.partid)
group by parts.id;

MySQL Multiple Where Conditions on Same Field in a Join

I have a table called "orders" with
order_id
customer_name
item
and am joining it to another table called "orders_requests" containing
order_id
requests
One row in "orders" may have zero or more rows in "order_requests." I'm trying to perform a query to find "orders" that have "orders_requests" of "rush processing" and "free shipping." I'm leaning towards a RIGHT OUTER JOIN with the "orders_requests" table on the left so it only returns results if a corresponding "orders" row exists, but I've had no success with either of these queries.
This one doesn't work since it pulls rows that are rush processing or free shipping.
SELECT DISTINCT orders.order_id, orders.* ,
FROM orders_requests
RIGHT OUTER JOIN orders ON orders_requests.order_id = orders.order_id
WHERE orders_requests.requests
IN ('rush processing', 'free shipping')
And this one clearly doesn't work since it's impossible for any one row to match both conditions.
SELECT DISTINCT orders.order_id, orders.* ,
FROM orders_requests
RIGHT OUTER JOIN orders ON orders_requests.order_id = orders.order_id
WHERE orders_requests.requests = 'rush processing'
AND orders_requests.requests = 'free shipping'
Is what I'm trying to do possible with my table setup do I need to change the structure?
I am not sure if this would work since I cannot test it atm but try this:
select a.order_id, b.*, c.*
from orders a
left outer join orders_requests b on b.order_id = a.order_id
left outer join orders_requests c on c.order_id = a.order_id
where b.requests = 'rush processing' and c.requests = 'free shipping'