MySQL Multiple Where Conditions on Same Field in a Join - mysql

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'

Related

SQL Left Join a Table on a Left Joined Table

Iam currently trying to left join a table on a left joined table as follows.
I have the tables:
accounts (id, vorname, nachname)
projektkurse (id, accounts_id, projektwochen_id)
projektkurs_einzel (id, projektkurse_id)
projektkurs_einzel_zeiten (id, date, shift, projektkurs_einzel_id)
Now I want to get every account and the amount times they have an entry inside of projektkurs_einzel_zeiten, which should also be unique. So having the same date and shift multiple times does not count as multiple entries. The result should also be limited by the column projektwochen_id from the table projektkurse. This column should match a certain value for example 8.
Some Accounts don't have any entries in projektkurse, projektkurs_einzel and projektkurs_einzel_zeiten, this is why my first thought was using LEFT JOIN like this:
SELECT accounts.id, accounts.vorname, accounts.nachname, COUNT(DISTINCT projektkurs_einzel_zeiten.date, projektkurs_einzel_zeiten.shift) AS T
FROM accounts
LEFT JOIN projektkurse on accounts.id = projektkurse.creator_id
LEFT JOIN projektkurs_einzel on projektkurse.id = projektkurs_einzel.projektkurs_id
LEFT JOIN projektkurs_einzel_zeiten ON projektkurs_einzel.id = projektkurs_einzel_zeiten.projektkurs_einzel_id
WHERE projektkurse.projektwochen_id = 8
GROUP BY accounts.id
This query does not achieve exactly what I want. It only returns accounts that have atleast one entry in projektkurse even if they have none in projektkurs_einzel and projektkurs_einzel_zeiten. The Count is obviously 0 for them but the accounts that have no entries in projektkurse are being ignored completly.
How can I also show the accounts that don't have entries in any other table with the Count 0 aswell?
I would recommend writing the query like this:
SELECT a.id, a.vorname, a.nachname,
COUNT(DISTINCT pez.date, pez.shift) AS T
FROM accounts a LEFT JOIN
projektkurse
ON a.id = pk.creator_id AND
pk.projektwochen_id = 8 LEFT JOIN
projektkurs_einzel pe
ON pk.id = pe.projektkurs_id LEFT JOIN
projektkurs_einzel_zeiten pez
ON pe.id = pez.projektkurs_einzel_id
GROUP BY a.id, a.vorname, a.nachname;
Notes:
Your problem is fixed by moving the WHERE condition to the ON clause. Your WHERE turns the outer join into an inner join, because NULL values do not match.
Table aliases make the query easier to write and to read.
It is a best practice to include all unaggregated columns in the GROUP BY. However, assuming that id is unique, your formulation is okay (due to something called "functional dependencies").
You should not use eft join table's column ins where condition this work as inner join
You should move the where condition for a left joined table in the corresponding ON clause
SELECT accounts.id, accounts.vorname, accounts.nachname, COUNT(DISTINCT projektkurs_einzel_zeiten.date, projektkurs_einzel_zeiten.shift) AS T
FROM accounts
LEFT JOIN projektkurse on accounts.id = projektkurse.creator_id
AND projektkurse.projektwochen_id = 8
LEFT JOIN projektkurs_einzel on projektkurse.id = projektkurs_einzel.projektkurs_id
LEFT JOIN projektkurs_einzel_zeiten ON projektkurs_einzel.id = projektkurs_einzel_zeiten.projektkurs_einzel_id
GROUP BY accounts.id

Inner Join for list of records NOT in a second table (NOT Inner Join)

I have a table let's call it products with a list of Manufacturers and Products.
I have a second table let's call it Customer, Orders.
I can do a join to make a list of all the items from each manufacturer the customer ordered doing an Inner Join. Yet trying to do an Inner Join for the items they did not fails.
I tried an Inner Join with 'Orders.Product != Products.Product' but that only works where the Customer has one order. Once there is more than one order I get the same list I would have doing an Inner Join. Any thoughts? I'll try to make a SqlFiddle tonight but was hoping a quick description might help a MySql / Join expert who has done 'NOT Inner Join'before...
It is called an anti join, you can use left join with is null check:
select p.*
from products p
left join orders o on p.Product = o.Product
where o.product is null

If row exist in a table then use another tables value in SQL

What i would like to archieve:
Getting the correct sum of the total amount of the orders that has been cancelled of user id 2002.
Some pre information:
I am having deals which that has its price in deals.price and its id in deals.ID
I then have orders with a foreign key to deals.ID
Running this SQL:
select SUM(deals.price), orders.* from orders
JOIN deals ON deals.ID = orders.deal_id
where orders.user_id = 2002
and orders.cancelled = 1
Works just fine.
Here is where i get stuck:
As an addition to deals, each deals has products with their own prices.
Table is called deal_products, deal_products.price hold the price and deal_products.product_id has the ID of it.
A order is attached to a deal product in another table called order_products, where order_products.product_id = deal_products.product_id
To sum up: I would like to do is including a if inside the above SQL.
If a order has a row in order_products, get the order_products.product_id and find the price in deal_products (price) and use this instead of deals.price when SUM()'ing.
If there is no row it should use deals.price.
How can this be archieved? To first look in another table if there is a entry, and then further look in to a third table and get a value to use?
You can use COALESCE + LEFT JOIN:
select SUM(coalesce(dp.price, d.price)), o.*
from orders o JOIN deals d ON d.ID = o.deal_id
LEFT JOIN order_products op on op.order_id = o.id
LEFT JOIN deal_products dp on op.product_id = dp.product_id
where o.user_id = 2002 and o.cancelled = 1
group by ...;
COALESCE function returns first not null operand
LEFT [OUTER] JOIN = [INNER] JOIN + all rows of the structure on the left side of the LEFT JOIN keyword, which don't match the ON clause in the right structure.

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.

MySQL Multiple Joins in one query?

I have the following query:
SELECT
dashboard_data.headline,
dashboard_data.message,
dashboard_messages.image_id
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
So I am using an INNER JOIN and grabbing the image_id. So now, I want to take that image_id and turn it into images.filename from the images table.
How can I add that in to my query?
You can simply add another join like this:
SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
INNER JOIN images
ON dashboard_messages.image_id = images.image_id
However be aware that, because it is an INNER JOIN, if you have a message without an image, the entire row will be skipped. If this is a possibility, you may want to do a LEFT OUTER JOIN which will return all your dashboard messages and an image_filename only if one exists (otherwise you'll get a null)
SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
LEFT OUTER JOIN images
ON dashboard_messages.image_id = images.image_id
Just add another join:
SELECT dashboard_data.headline,
dashboard_data.message,
dashboard_messages.image_id,
images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
INNER JOIN images
ON dashboard_messages.image_id = images.image_id
I shared my experience of using two LEFT JOINS in a single SQL query.
I have 3 tables:
Table 1) Patient consists columns PatientID, PatientName
Table 2) Appointment consists columns AppointmentID, AppointmentDateTime, PatientID, DoctorID
Table 3) Doctor consists columns DoctorID, DoctorName
Query:
SELECT Patient.patientname, AppointmentDateTime, Doctor.doctorname
FROM Appointment
LEFT JOIN Doctor ON Appointment.doctorid = Doctor.doctorId //have doctorId column common
LEFT JOIN Patient ON Appointment.PatientId = Patient.PatientId //have patientid column common
WHERE Doctor.Doctorname LIKE 'varun%' // setting doctor name by using LIKE
AND Appointment.AppointmentDateTime BETWEEN '1/16/2001' AND '9/9/2014' //comparison b/w dates
ORDER BY AppointmentDateTime ASC; // getting data as ascending order
I wrote the solution to get date format like "mm/dd/yy" (under my name "VARUN TEJ REDDY")
Multi joins in SQL work by progressively creating derived tables one after the other.
See this link explaining the process:
https://www.interfacett.com/blogs/multiple-joins-work-just-like-single-joins/