So I know how to create the query using a JOIN but how do I turn this JOIN into a subquery? I have been trying all sorts of things but I just can't figure it out.
My join looks like this:
SELECT
c.email_address, o.order_id, o.order_date
FROM
customer c
JOIN orders o ON (c.customer_id = o.customer_id)
ORDER BY
order_date;
My attempt at creating the multiple table:
SELECT
c.email_address, o.order_id, o.order_date
FROM
customer c
WHERE
c.customer_id IN (SELECT o.customer_id FROM orders o)
ORDER BY
o.order_date;
I keep getting an error of unknown column for both order_id and order_date
Related
I currently am trying to write a query that shows customers with at least 5 orders and customer with no orders. Orders are tracked in their own table and in order to find customers with 0 orders we have to find the customers NOT IN orders. Below is my query I'm trying to use and it returns the same customer 5 times for zero orders.
with t1 as
(select o.customerNumber, c.customerName, count(o.orderNumber) as FiveOrders
from orders o join customers c on (o.customerNumber = c.customerNumber)
group by o.customerNumber having count(o.orderNumber) = 5),
t2 as
(select distinct o.customerNumber, c.customerName, count(o.orderNumber) as NoOrders
from orders o join customers c on (o.customerNumber = c.customerNumber)
group by c.customerNumber not in(select customerNumber from orders))
select distinct t1.customerNumber as FiveOrderNumber, t1.customerName as FiveOrderName,
t2.customerNumber as NoOrderNumber, t2.customerName as NoOrderName
from t1 join t2
order by NoOrderName;
Any and all help is appreciated thanks!
If the errors were only in the second table to, I think it is after using
having with condition NOT IN without any logical comparison, I think you can get wanted results easily like:
select distinct customerNumber, customerName, "0" as NoOrders
from customers
where customerNumber not in (Select customerNumber from orders)
If the group by is important, you can use it like in your code.
Zero or five could be counted together with LEFT JOIN
select c.customerNumber, max(c.customerName) customerName, count(o.orderNumber) as FiveOrdersOrZero
from customers c
left join orders o on o.customerNumber = c.customerNumber
group by c.customerNumber
having count(o.orderNumber) in ( 0, 5 )
order by FiveOrdersOrZero
I have two database tables: orders and customers.
I'm running a SQL to get all orders in June month.
If the Ship To and Bill To email are different, we are inserting two different records with both emails to customers table.
select o.order_id
, o.total
, c.customer_email
from orders o
left
join customers c
ON o.bill_email = c.customer_email
OR o.ship_email = c.customer_email
where DATE(o.order_date) >= '2020-06-01'
But this SQL is taking too much time to load because of the condition,
ON o.bill_email=c.customer_email
OR o.ship_email=c.customer_email
How can I add both conditions in ON clause?
Any help would be appreciated.
Use two left joins and put the results in separate columns rather than rows:
select o.order_id, o.total, cb.customer_email, so.customer_email
from orders o left join
customers cb
on o.bill_email = cb.customer_email left join
customers cs
o.ship_email = cs.customer_email
where o.order_date >= '2020-06-01';
Note that the date() function is not needed.
That said, this seems more easily expressed as:
select o.order_id, o.total, o.bill_email
from orders o
where o.order_date >= '2020-06-01'
union all
select o.order_id, o.total, o.ship_email
from orders o
where o.order_date >= '2020-06-01' and s.ship_email <> o.bill_email;
I am trying to determine the customers spending behavior by writing a query to select the top 10 highest spenders.
I have the following query and it works fine:
SELECT c.CustomerID
, SUM(Quantity * UnitPrice) Total_Spent
FROM Orders o
JOIN OrderDetails d
ON d.OrderID = o.OrderID
JOIN Customers c
ON c.CustomerID = o.CustomerID
GROUP
BY c.CustomerID
ORDER
BY Total_Spent
limit 10;
However, I want to create a subquery instead of having this complicated one. I have tried the following but it doesn't work:
SELECT Customers.CustomerID
FROM Customers
JOIN (
SELECT SUM(Quantity *UnitPrice) as Total_Spent
FROM Orders
JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID) Orders
ON Orders.CustomerID = Customers.CustomerID
GROUP BY Customers.CustomerID
ORDER BY Total_Spent
LIMIT 10;
I don't know what the problem is. (I am kinda new in SQL)
You can simplify your query because you don't need the customers table. That and table aliases should make your query simpler:
SELECT o.CustomerID, SUM(od.Quantity * od.UnitPrice) as Total_Spent
FROM Orders o JOIN
OrderDetails od
ON o.OrderID = od.OrderID
GROUP BY o.CustomerID
ORDER BY Total_Spent DESC
LIMIT 10;
I need to do this but with a subquery, not a join. My problem is, how can I use a subquery to display another column? I could grab the info from there, but I'll be missing the order_date column from the orders table. Can I use a subquery to display it?
SELECT CONCAT(c.customer_first_name, ' ' , c.customer_last_name) AS customer_name, MAX(o.order_date) AS recent_order_date
FROM customers AS c
JOIN orders AS o
ON c.customer_id = o.customer_id
GROUP BY customer_name
ORDER BY MAX(o.order_date) DESC
It's not at all clear what resultset you are trying to return, but it looks an awful like the like the ubiquitous "latest row" problem.
The normative pattern for the solution to that problem is to use a JOIN to the inline view. If there's not a unique constraint, you run the possibility of returning more than one matching row.
To get the latest order (the row in the orders table with the maximum order_date for each customer, assuming that the (customer_id, order_date) tuple is unique, you can do something like this:
SELECT o.*
FROM ( SELECT n.customer_id
, MAX(n.order_date) AS latest_order_date
FROM orders n
GROUP BY n.customer_id
) m
JOIN orders o
ON o.customer_id = m.customer_id
AND o.order_date = m.latest_order_date
If you want to also retrieve columns from the customers table based on the customer_id returned from orders, you'd use a JOIN (not a subquery)
SELECT CONCAT(c.customer_first_name,' ',c.customer_last_name) AS customer_name
, c.whatever
, o.order_date AS recent_order_date
, o.whatever
FROM ( SELECT n.customer_id
, MAX(n.order_date) AS latest_order_date
FROM orders n
GROUP BY n.customer_id
) m
JOIN orders o
ON o.customer_id = m.customer_id
AND o.order_date = m.latest_order_date
JOIN customers c
ON c.customer_id = o.customer_id
ORDER BY o.order_date DESC, o.customer_id DESC
As I mentioned before, if a given customer can have two orders with the exact same value for order_date, there's potential to return more than one order for each customer_id.
To rectify that, we can return a unique key from the inline view, and use that in the join predicate to guarantee only a single row returned from orders.
(NOTE: this approach is specific to MySQL, with this syntax, other RDBMS will throw an error that essentially says "the GROUP BY must include all non-aggregates". But MySQL allows it.)
SELECT CONCAT(c.customer_first_name,' ',c.customer_last_name) AS customer_name
, c.whatever
, o.order_date AS recent_order_date
, o.whatever
FROM ( SELECT n.customer_id
, MAX(n.order_date) AS latest_order_date
, n.order_id
FROM orders n
GROUP BY n.customer_id
) m
JOIN orders o
AND o.customer_id = m.customer_id
AND o.order_date = m.latest_order_date
AND o.order_id = n.order_id
JOIN customers c
ON c.customer_id = o.customer_id
ORDER BY o.order_date DESC, o.customer_id DESC
I am not really sure i understand your question, but i think this works... (not tested though...)
SELECT
(
SELECT
CONCAT(c.customer_first_name, ' ' , c.customer_last_name)
FROM
customers c
WHERE
c.customer_id = o.customer_id
LIMIT 1
) AS customer_name,
MAX(o.order_date) AS recent_order_date
FROM
orders o
GROUP BY
customer_name
ORDER BY
MAX(o.order_date) DESC
I would like to find those customers, who have not made any orders yet.
I have found some queries to find customer wise total no. of orders, but did not able to find/get any query, which returns me those customers ids, which are not into orders table.
Also would like to sort the results by date, like in last month, last year etc.
Any help/idea would be appreciated.
Thanks !
How about
SELECT c.*
FROM Customers c LEFT JOIN
Orders o ON c.CustomerID = o.CustomerID
WHERE o.CustomerID IS NULL
or
SELECT c.*
FROM Customers c
WHERE NOT EXISTS (SELECT 1 FROM Orders o WHERE o.CustomerID = c.CustomerID)
select c.* from Customers c
where c.CustomerID NOT IN (select o.CustomerID from Orders o)
select customer_name from customer
where customer_id not in (select customer_id from orders);