SQL Retrieve Names Based on Multiple Tables - sql

So I have three tables. CUSTOMER(CustomerID, LastName, FirstName), PURCHASE(PurchaseID, ItemName), and TRANSACTION(CustomerID, PurchaseID, Date).
The problem I am having is that I need to get the full name of the customers who specifically buy the both items "Paint" and "Books" but when I run my code nothing comes up. Here is what I have:
SELECT CUSTOMER.FirstName, CUSTOMER.LastName
FROM CUSTOMER, PURCHASE
WHERE PURCHASE.Item = 'Paint' AND PURCHASE.Item = 'Books'
GROUP BY CUSTOMER.LastName, CUSTOMER.FirstName;
Please help, I am really new to this and would really like some help.

This type of problem is called Relational Division.
SELECT CUSTOMER.FirstName, CUSTOMER.LastName
FROM CUSTOMER
INNER JOIN TRANSACTION
ON CUSTOMER.CustomerID = TRANSACTION.CustomerID
INNER JOIN PURCHASE
ON TRANSACTION.PurchaseID = PURCHASE.PurchaseID
WHERE PURCHASE.Item IN ('Paint', 'Books') -- list all items here
GROUP BY CUSTOMER.LastName, CUSTOMER.FirstName
HAVING COUNT(DISTINCT PURCHASE.Item) = 2 -- the total number of items searched
SQL of Relational Division
if there is a UNIQUE constraint that was enforced for every ItemName on each transaction, you can use *
SELECT CUSTOMER.FirstName, CUSTOMER.LastName
FROM CUSTOMER
INNER JOIN TRANSACTION
ON CUSTOMER.CustomerID = TRANSACTION.CustomerID
INNER JOIN PURCHASE
ON TRANSACTION.PurchaseID = PURCHASE.PurchaseID
WHERE PURCHASE.Item IN ('Paint', 'Books')
GROUP BY CUSTOMER.LastName, CUSTOMER.FirstName
HAVING COUNT(*) = 2

NO CONNECTION..
SELECT DISTINCT CUSTOMER.FirstName, CUSTOMER.LastName
FROM CUSTOMER A
JOIN TRANSACTION B
ON A.CUSTOMERID=B.CUSTOMERID
JOIN PURCHASE C
ON B.PURCHASEID=C.PURCHASEID AND C.ITEM='Paint'
JOIN PURCHASE D
ON B.PURCHASEID=D.PURCHASEID AND D.C.Item = 'Books'

SELECT CUSTOMER.FirstName, CUSTOMER.LastName
FROM CUSTOMER C, PURCHASE P, TRANSACTION T
WHERE
C.CUSTOMERID = T.CUSTOMERID AND T.PurchaseID = P.PurchaseID
AND P.Item IN ('Paint','Books')
This is pseudo code. Try it out by yourselves.

You need to JOIN tables. Try
SELECT CUSTOMER.FirstName, CUSTOMER.LastName
FROM CUSTOMER
INNER JOIN TRANSACTION ON TRANSACTION.CustomerID=CUSTOMER.CustomerID
INNER JOIN PURCHASE ON PURCHASE.PurchaseID=TRANSACTION.PurchaseID
WHERE PURCHASE.Item = 'Paint' OR PURCHASE.Item = 'Books'
GROUP BY CUSTOMER.LastName, CUSTOMER.FirstName
HAVING COUNT(DISTINCT PURCHASE.Item) >= 2;

Related

SQL Server stored procedure query multiple tables

I am querying a SQL Server database using a stored procedure.
My database tables include:
Customers
SalesOrders - Linked to the customers with an id
SalesOrderLines - Linked to the SalesOrders with an id
SalesOrderReleases - Linked to the SalesOrderLines with an id, stores the quantity on the order line that has been released and ready to manufacture, the SalesOrderLine quantity can be all on one release or split up on multiple
FinishedGoods - linked to the SalesOrderLines with an id, stores the quantity of the SalesOrderLine where manufacturing is complete, the SalesOrderLine quantity can be all on one FinishedGood entry or split up on multiple
I need to retrieve all the customers that have SalesOrderLines with SalesOrderReleases and FinishedGoods where the total quantity finished is less than the total quantity released
I have tried this SQL code but Customers appear repeatedly in the results
SELECT
Customer.ID, Customer.Name
FROM
Customer
INNER JOIN
SalesOrder ON Customer.ID = SalesOrder.CustomerID
INNER JOIN
SalesOrderLine ON SalesOrder.ID = SalesOrderLine.SalesOrderID
INNER JOIN
SalesOrderRelease ON SalesOrderLine.ID = SalesOrderRelease.SalesOrderLineID
INNER JOIN
FinishedGood ON SalesOrderLine.ID = FinishedGood.SalesOrderLineID AND FinishedGood.Quantity < SalesOrderRelease.Quantity
I am looking for a SQL code snippet that will query multiple tables the way I have described.
try this code:
SELECT Customer.ID, Customer.Name FROM Customer
INNER JOIN SalesOrder ON Customer.ID = Order.CustomerID
INNER JOIN SalesOrderLine ON Order.ID = OrderLine.OrderID
INNER JOIN
(SELECT OrderID, OrderLineID, SUM (Quantity) AS SRQuantity FROM
SalesOrderRelease GROUP BY OrderID, OrderLineID) AS SRQ
ON SRQ.OrderID = SalesOrderLine.OrderID
INNER JOIN
(SELECT OrderLineID, SUM (Quantity) AS FGQuantity FROM
FinishedGoods GROUP BY OrderLineID) AS FGQ
ON SRQ.OrderLineID = FGQ.OrderLineID
WHERE FGQ.FgQuantity < SRQ.SRQuantity
Credits to Sergey for his answer, I was able to use the sample code he provided with several slight modifications:
SELECT Customer.ID, Customer.Name FROM Customer
INNER JOIN SalesOrder ON Customer.ID = SalesOrder.CustomerID
INNER JOIN SalesOrderLine ON SalesOrder.ID = SalesOrderLine.SalesOrderID
INNER JOIN
(SELECT SalesOrderID, SalesOrderLineID, SUM (Quantity) AS SRQuantity FROM
SalesOrderRelease GROUP BY SalesOrderID, SalesOrderLineID) AS SRQ
ON SRQ.SalesOrderLineID = SalesOrderLine.SalesOrderID
LEFT JOIN
(SELECT SalesOrderLineID, SUM (Quantity) AS FGQuantity FROM
FinishedGood GROUP BY SalesOrderLineID) AS FGQ
ON SRQ.SalesOrderLineID = FGQ.SalesOrderLineID
WHERE ISNULL(FGQ.FgQuantity, 0) < SRQ.SRQuantity
The last join needed to be a Left Join
When comparing the FgQuantity and the SRQuantity in the last line, I needed to have it check for NULL values
With these modifications everythings works perfectly!

need help to write a query about this db

I have this DB and I need help with this query
Find the customer ID, first name, last name and the movie Name
of the customer that bought the most ticket in that day
I found the customer who bought the highest number of tickets in that day, now I need to find the movies that he bought tickets for
SELECT c.*, COUNT(*) 'bought'
FROM customer c JOIN ticket t ON c.customerId=t.customerId
GROUP BY c.customerId
HAVING bought=(SELECT MAX(T1.CNT)
FROM (SELECT COUNT(*) AS CNT
FROM customer c JOIN ticket t ON c.customerId=t.customerId
GROUP BY c.customerId) AS T1)
So without building the database and populating it with dummy data I can't test this, but I think I found a solution for you.
SELECT C.CUSTOMERID, C.FIRSTNAME, C.LASTNAME, M.TITLE
FROM CUSTOMER C JOIN TICKET T ON C.CUSTOMERID = T.CUSTOMERID JOIN SHOWS S ON T.SHOWNUMBER = S.SHOWNUMBER JOIN MOVIE M ON M.MOVIEID = S.MOVIEID
WHERE C.CUSTOMERID IN(
SELECT C1.CUSTOMERID FROM(
SELECT CUST.CUSTOMERID, COUNT(*) 'BOUGHT'
FROM CUSTOMER CUST JOIN TICKET TICK ON CUST.CUSTOMERID = TICK.CUSTOMERID
GROUP BY CUST.CUSTOMERID
HAVING BOUGHT = (SELECT MAX(T1.CNT) FROM (SELECT COUNT(*) AS CNT FROM CUSTOMER CUSTO JOIN TICKET TICKE ON CUSTO.CUSTOMERID = TICKE.CUSTOMERID GROUP BY CUSTO.CUSTOMERID)AS T1) AS C1);

I need my query to return where it will return where an item was purchased by more than 3 customers. However, my query keeps returning Null

I have confirmed that there is instances where an item was purchased more than 3 times by 3 SEPERATE customers. However, my code keeps returning Null. I have tried several different variations of the code below, but I get either Null or an error message stating "Ambiguous column name 'Customer_ID'."
I have also tried aliasing it, but with no luck. Where am I going wrong?
SELECT First_Name, Last_Name, Country, Address, State, Zip, Product_Name
FROM Orders
JOIN Customer ON Orders.Customer_ID = Customer.Customer_ID
JOIN Amazon_Inventory ON Orders.Inventory_ID = Amazon_Inventory.Inventory_ID
JOIN Shipment ON Amazon_Inventory.Shipment_ID = Shipment.Shipment_ID
JOIN Product ON Shipment.Product_ID = Product.Product_ID
JOIN Product_Listing ON Product.Listing_ID = Product_Listing.Listing_ID
WHERE ORDER_ID IN
(SELECT Customer_ID, Inventory_ID
FROM Orders
GROUP BY Customer_ID, Inventory_ID
HAVING COUNT (Order_ID) >3 AND COUNT (INVENTORY_ID) >3);
The error is on IN subquery,you can't use IN to compare multiple fields.
If I understand correct you might expect this.
You could provide some sample data and expect result.I will edit my answer.
SELECT First_Name, Last_Name, Country, Address, State, Zip, Product_Name
FROM Orders
JOIN Customer ON Orders.Customer_ID = Customer.Customer_ID
JOIN Amazon_Inventory ON Orders.Inventory_ID = Amazon_Inventory.Inventory_ID
JOIN Shipment ON Amazon_Inventory.Shipment_ID = Shipment.Shipment_ID
JOIN Product ON Shipment.Product_ID = Product.Product_ID
JOIN Product_Listing ON Product.Listing_ID = Product_Listing.Listing_ID
WHERE Customer.Customer_ID IN
(SELECT Customer_ID
FROM Orders
GROUP BY Customer_ID
HAVING COUNT (1) >3 );
You are almost there. I would suggest you to use alias to your tables (that would solve the ambiguous errors), and also, you are using an IN referring to a SELECT with more than 1 column being selected (A tip: I would use an EXISTS instead of a IN whenever possible - but that's not the case - or at least it doesn't seems like the case with the info provided).
So, using aliases I would end up with something like this:
SELECT
*
/* Place appropriate alias in each field selected => First_Name, Last_Name, Country, Address, State, Zip, Product_Name */
FROM Orders AS OR
JOIN Customer AS CU ON Orders.Customer_ID = Customer.Customer_ID
JOIN Amazon_Inventory AS AI ON Orders.Inventory_ID = Amazon_Inventory.Inventory_ID
JOIN Shipment AS SH ON Amazon_Inventory.Shipment_ID = Shipment.Shipment_ID
JOIN Product AS PR ON Shipment.Product_ID = Product.Product_ID
JOIN Product_Listing AS PL ON Product.Listing_ID = Product_Listing.Listing_ID
WHERE
EXISTS
(SELECT 1 FROM Orders OREX
WHERE OREX.Inventory_ID = OR.Inventory_ID
GROUP BY OREX.Customer_ID, OREX.Inventory_ID
HAVING COUNT(1)>3);
I'm thinking something like this:
SELECT
c.Customer_ID, i.Inventory_ID,
c.First_Name, c.Last_Name, c.Country, c.Address, c.State, c.Zip,
p.Product_Name
FROM Orders o
JOIN Customer c ON o.Customer_ID = c.Customer_ID
JOIN Amazon_Inventory i ON o.Inventory_ID = i.Inventory_ID
JOIN Shipment s ON i.Shipment_ID = s.Shipment_ID
JOIN Product p ON s.Product_ID = p.Product_ID
JOIN Product_Listing l ON p.Listing_ID = l.Listing_ID
)
WHERE Inventory_ID IN (
SELECT Inventory_ID
FROM Orders JOIN Customer ON Orders.Customer_ID = Customer.Customer_ID
GROUP BY Inventory_ID
HAVING COUNT (DISTINCT Customer_ID) > 3
);

Finding Customers Last Price Paid

I'm trying to find a way to get customers last price paid the code we have at the moment is:
SELECT Product.ProductCode,
COUNT(Product.ProductCode) AS [Qty Baught],
Product.Description,
Customer.CustomerCode,
Customer.Name,
MAX(OrderHeader.DateTimeCreated) AS [Date],
OrderLine.UnitSellPriceInCurrency AS Sell
FROM Customer
INNER JOIN OrderHeader ON Customer.CustomerID = OrderHeader.CustomerID
INNER JOIN OrderLine ON OrderHeader.OrderID = OrderLine.OrderID
INNER JOIN Product ON OrderLine.ProductID = Product.ProductID
GROUP BY Product.Description,
Product.ProductCode,
Customer.CustomerCode,
Customer.Name,
OrderLine.UnitSellPriceInCurrency
HAVING (Product.ProductCode = 'bcem002')
AND (Customer.CustomerCode = '1000')
ORDER BY MAX(OrderHeader.DateTimeCreated) DESC
This code shows every time the price changed but I only want to see the last price, But the DateCreated and the price paid (UnitSellPriceInCurrency) are on different tables.
Is there a way to Group (UnitSellPriceInCurrency) by (DateCreated) or an alternative way of doing it.
I'm fairly new at this so if there's an obvious way of doing this sorry.
Edit: What i'm getting at the moment with new code, Most of the prices i'm getting up are unrelated to the products
What I want is to get just the last price paid showing but in a way I can change the customer and the product that I'm searching for.
One option might be to use a sub-select utilizing TOP to specify that you only want to retrieve one record, and make sure that it is the "latest" by using the ORDER BY:
SELECT Product.ProductCode,
COUNT(Product.ProductCode) AS [Qty Baught],
Product.Description,
Customer.CustomerCode,
Customer.Name,
MAX(OrderHeader.DateTimeCreated) AS [Date],
(SELECT TOP 1 O.UnitSellPriceInCurrency
FROM OrderLine O
INNER JOIN OrderHeader OH ON O.OrderID = OH.OrderID
WHERE OH.CustomerID = Customer.CustomerID AND O.ProductID = Product.ProductID
ORDER BY OH.DateTimeCreated DESC) AS LatestPrice
FROM Customer
INNER JOIN OrderHeader ON Customer.CustomerID = OrderHeader.CustomerID
INNER JOIN OrderLine ON OrderHeader.OrderID = OrderLine.OrderID
INNER JOIN Product ON OrderLine.ProductID = Product.ProductID
WHERE (Customer.CustomerCode = '1000') AND (Product.ProductCode = 'bcem002')
GROUP BY Product.Description,
Product.ProductCode,
Product.ProductID,
Customer.CustomerCode,
Customer.Name,
Customer.CustomerID
ORDER BY [Date] DESC
In this example LatestPrice will contain the last inserted UnitSellPriceInCurrency for each Customer and product. I'm not sure if the query makes sense with your data (why get only the last price) but it's how I interpreted your request. The query will still return all OrderHeaders though.
Can you please check of this works alright. It would be better if you posted a snapshot of the current result and the expected result you need.
Select
*
FROM
(
SELECT Product.ProductCode,
COUNT(Product.ProductCode) AS [Qty Baught],
Product.Description,
Customer.CustomerCode,
Customer.Name,
OrderHeader.DateTimeCreated AS [Date],
OrderLine.UnitSellPriceInCurrency AS Sell
RANK() OVER (PARTITION BY Customer.CustomerCode,Customer.Name, OrderLine.UnitSellPriceInCurrency ORDER BY OrderHeader.DateTimeCreated) rnk
FROM Customer
INNER JOIN OrderHeader ON Customer.CustomerID = OrderHeader.CustomerID
INNER JOIN OrderLine ON OrderHeader.OrderID = OrderLine.OrderID
INNER JOIN Product ON OrderLine.ProductID = Product.ProductID
WHERE Product.ProductCode = 'bcem002'
AND Customer.CustomerCode = '1000'
GROUP BY Product.Description,
Product.ProductCode,
Customer.CustomerCode,
Customer.Name,
OrderLine.UnitSellPriceInCurrency
) tbl1
WHERE tbl1.rnk =1
;

Joining on a group by

Lets say that I have three tables, customers, orders and orderDetails.
I'm doing this:
SELECT orders.ordersId, sum(orderDetails.total)
FROM orders
LEFT OUTER JOIN orderDetails ON orders.ordersId = orderDetails.ordersId
GROUP BY orders.ordersId
But lets say the orders table contains customersId. How do I join on the customers table so that I can also add the customer's name to the fields selected?
Thanks,
Barry
SELECT orders.ordersId, sum(orderDetails.total), customer.name
FROM orders
LEFT OUTER JOIN orderDetails ON orders.ordersId = orderDetails.ordersId
LEFT OUTER JOIN customer on customer.customerid = orders.customerid
GROUP BY orders.ordersId , customer.name
Try that out or something similar.
you can do it this way, which will let you get more than customer name if needed:
SELECT o.ordersId, o.orderTotal, c.customername, c.(other customer data)
FROM
(
SELECT orders.ordersId
, sum(orderDetails.total) as orderTotal
, orders.customersid
FROM orders
LEFT OUTER JOIN orderDetails
ON orders.ordersId = orderDetails.ordersId
GROUP BY orders.ordersId, orders.customersid
) o
LEFT JOIN customers c
ON o.customersid = c.customersid