Okay, I've perused this site, a couple that members here have suggested, sql textbooks, etc.
The problem:
List customer name, order date, number ordered, quoted price, amount billed and description for items ordered from Premiere Products. Organize this report by order date with customer name
The tables:
SQL> desc customer
Name
----------------------
CUSTOMER_NUM
CUSTOMER_NAME
STREET
CITY
STATE
ZIP
BALANCE
CREDIT_LIMIT
REP_NUM
SQL> desc orders
Name
----------------------
ORDER_NUM
ORDER_DATE
CUSTOMER_NUM
SQL> desc order_line
Name
----------------------
ORDER_NUM
PART_NUM
NUM_ORDERED
QUOTED_PRICE
SQL> desc part
Name
----------------------
PART_NUM
DESCRIPT
ON_HAND
CLASS
WAREHOUSE
PRICE
Here's what I am using for a query:
SQL> SELECT CUSTOMER.CUSTOMER_NAME, ORDERS.ORDER_DATE,
2 ORDER_LINE.NUM_ORDERED, ORDER_LINE.QUOTED_PRICE,
3 SUM(Num_Ordered*Quoted_Price) AS Amt_Billed,
4 PART.DESCRIPT
5 FROM customer
6 INNER JOIN CUSTOMER INNER JOIN ORDERS ON
CUSTOMER.CUSTOMER_NUM =ORDERS.CUSTOMER_NUM
7 INNER JOIN ORDER_LINE ON ORDERS.ORDER_NUM = ORDER_LINE.ORDER_NUM
8 Inner JOIN ORDER_LINE ON PART.PART_NUM = ORDER_LINE.PART_NUM;
Inner JOIN ORDER_LINE ON PART.PART_NUM = ORDER_LINE.PART_NUM
*
ERROR at line 8:
ORA-00905: missing keyword
Ive tried it several times, even made an access table for it, and the SQL there is basically the same as what I have here. I'm using Oracle 11g.
Getting your SQL formatted helps follow the relationships between the tables. Notice my simplified indentation and showing the left-side table joined to the right-side and the ON clause shows columnar relation between them.
Once that is done, then get the rest of your columns for selection, summation, group by, order by, etc
SELECT
c.customer_name,
o.order_date,
ol.num_ordered,
ol.quoted_price,
ol.num_ordered * ol.quoted_price as amt_Billed,
p.descript
from
customer c
join orders o
ON c.customer_num = o.customer_num
join order_line ol
ON o.order_num = ol.order_num
join part p
ON ol.part_num = p.part_num
order by
o.order_date,
c.customer_name
Since your query is showing the amount per line item of things ordered, you dont need a "SUM()", you can just multiply the columns outright as a per-line total amount as you are showing each part actually ordered.
Also notice the simplified alias name references of each table vs writing full length of each table name repeatedly.
Yeap, joins again :)
INNER JOIN CUSTOMER INNER JOIN ORDERS ON
You're missing the ON in CUSTOMER or you have an extra INNER JOIN CUSTOMER. Most likely the second one.
try
SQL> SELECT CUSTOMER.CUSTOMER_NAME, ORDERS.ORDER_DATE,
ORDER_LINE.NUM_ORDERED, ORDER_LINE.QUOTED_PRICE,
SUM(Num_Ordered*Quoted_Price) AS Amt_Billed,
PART.DESCRIPT
FROM customer
INNER JOIN ORDERS ON CUSTOMER.CUSTOMER_NUM =ORDERS.CUSTOMER_NUM
INNER JOIN ORDER_LINE ON ORDERS.ORDER_NUM = ORDER_LINE.ORDER_NUM
Inner JOIN PART ON PART.PART_NUM = ORDER_LINE.PART_NUM;
Line 6 was an incorrect JOIN statement
Line 8 was joining to wrong table
Related
I'm doing practice exam material for a distance education course. I have the following three relations (simplified here):
salesperson(emp#, name, salary)
order(order#, cust#, emp#, total)
customer(cust#, name, city)
I'm stuck on a pair of SQL queries.
Display all customer info for customers with at least 1 order.
SELECT * FROM customer
INNER JOIN order ON order.cust# = customer.cust#
GROUP BY cust#;
Display all customer info for customers with at least 2 orders.
SELECT cust#, name, city, industry-type FROM customer
INNER JOIN order ON order.cust# = customer.cust#
GROUP BY cust#
HAVING COUNT(cust#) > 2;
I realize these are misguided attempts resulting from a poor understanding of SQL, but I've spent a ton of time on W3School's SQL Query example tool (https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_where) without getting anywhere, and I finally need some "real" help.
You can try to use subquery to get count by cust# then do inner join to make it.
SELECT c.*
FROM (
SELECT cust# , COUNT(*) cnt
FROM order
GROUP BY cust#
) o INNER JOIN customer c ON c.cust# = o.cust#
WHERE o.cnt > 2
You can change table names according to your DB. Following queries you can directly run in W3Schools
Display all customer info for customers with at least 1 order.
SELECT * FROM customers as cust JOIN orders as o ON o.customerid =
cust.customerid GROUP BY o.customerid;
Display all customer info for customers with at least 2 orders.
SELECT * FROM customers as cust JOIN orders as O ON O.CustomerID = cust.CustomerID GROUP BY cust.CustomerID HAVING COUNT(cust.CustomerID) > 2;
I am struggling with a sql statement. I am hoping a guru can help a beginner out, currently I have multiple select in statements.. but think there is a better way as I have been stuck.
Below are the tables and pertinent columns in each table
country
-country_id
barcodes_banned_in_country
-barcode(varchar)
-country_id
-country_name
orders
-order_id
-country_name
item
-order_id
-item_id
-barcode(varchar)
The goal is to get all orders that are banned based off the barcode banned list.
Any help with this sql statement would be appreciated.
One option uses exists:
select o.*
from orders o
where exists (
select 1
from barcodes_banned_in_country bic
inner join item i on i.barcode = bic.barcode
where i.order_id = o.order_id and bic.country_name = o.country_name
)
This brings all orders whose at least one item have a barcode that is banned in the order's country.
If, on the other hand, you want the list of the banned barcodes per order, then you can join and aggregate:
select o.order_id, o.country_name, listagg(i.barcode, ',') banned_barcodes
from orders o
inner join item i
on i.order_id = o.order_id
inner join barcodes_banned_in_country bic
on i.barcode = bic.barcode
and bic.country_name = o.country_name
group by o.order_id, o.country_name
Note that, as commented by MT0, you should really be storing the id of the country in orders rather than the country name. Accordingly, you wouldn't need the country name in the banned barcodes table.
EDIT: Added the query I came up with.
I'm a beginner at SQL (having it be taught as part of a database management class I am currently taking). One of my projects is to create a database revolving around customers and their orders. For this project, I have to make four tables:
Customer (PK = CustomerID),
Invoice (PK = InvoiceID/ FK = CustomerID),
Product (PK = ProductSKU), and
Invoice_Item (PK = FK Invoice ID + FK ProductSKU).
I have to make a query that asks the question of "What customers have ordered more than 3 of a certain item?" The query contains the fields of the CustomerID (C_ID), CustomerName (C_BUS), InvoiceID (I_NUM), ProductSKU (P_SKU), and ProductAmountOrdered (II_ORDERED) (attribute of the Invoice_Item table). Also note that the Invoice_ID and ProductSKU attributes in the query are coming from the Invoice_Item table. Now, I answered the question with the help of some joins, but there is a catch. The customer still satisfies the criteria if they have ordered more than 3 items across multiple orders (say they order 2 in one order and 2 in another). This is the part that is tripping me up. What is the best way to go about doing this? I have looked around and haven't found anything that seems like it would solve this question. Any help wold be greatly appreciated!
Here is the code that I have so far:
SELECT CUSTOMER.C_ID, C_BUS, P_SKU, INVOICE.I_NUM, INVOICE_ITEM.II_ORDERED
FROM CUSTOMER, INVOICE, INVOICE_ITEM
WHERE CUSTOMER.C_ID = INVOICE.C_ID
AND INVOICE.I_NUM = INVOICE_ITEM.I_NUM
AND INVOICE_ITEM.P_SKU = 'P0548'
AND II_ORDERED > 3
ORDER BY C_BUS DESC;
I understand that this might not be the best syntax, but this is what I managed using my textbook as a reference.
Please modify the queries as per your naming standards.
query for the customers who ordered more then three of a certain item across all their invoices:
select c.customer_id,
c.customer_name,
ii.product_sku,
sum(ii.ProductAmountOrdered)
as total_quantity_ordered
from customer c
inner join invoice i on c.customer_id = i.customer_id
inner join invoice_item ii on i.invoice_id = ii.invoice_id
group by c.customer_id,
c.customer_name,
ii.product_sku
having sum(ii.ProductAmountOrdered) >= 3;
Query to fetch customers that ordered more then 3 of a product in a single order/invoice:
select c.customer_id,
c.customer_name,
ii.invoice_id,
ii.product_sku,
sum(ii.ProductAmountOrdered)
as total_quantity_ordered
from customer c
inner join invoice i on c.customer_id = i.customer_id
inner join invoice_item ii on i.invoice_id = ii.invoice_id
group by c.customer_id,
c.customer_name,
ii.invoice_id,
ii.product_sku
having sum(ii.ProductAmountOrdered) >= 3;
I have two tables called 'Customers' and 'Orders'. Tables column names are as follow:
Customers: id, name, address
Orders: id, person_id, product, price
The desired outcome is to query all customers with one of their latest purchases. I have a lot of duplicates in 'Orders' table whereby two records with same time-stamp due to some bug.
I have written the following code but the issue is that the query does not return table 2(Orders) column values. Can anyone advise what the issue is?
SELECT C.Id,C.Name, O.item, O.price, O.product
FROM Customers C
LEFT JOIN
(
SELECT TOP 1 person_id
FROM Orders
WHERE status = 'Pending'
) O ON C.ID = O.person_id
Results: O.item, O.price, O.product values are all null
Edit: Sample Data
ID/ NAME/ ADDRESS/
1/ A/ Ad1/
2/ B/ Ad2/
3/ C/ Ad3/
ID/ Person ID/ PRODUCT PRICE/ Created Date
ID-1234/ 1/ Book/ $5/ 26-2-2017
ID-1235/ 1/ Book/ $5/ 26-2-2017
ID-1236/ 2/ Calendar/ $10/ 4-2-2017
ID-1238/ 1/ Pen/ $2/ 1-1-2016
Assuming that the id column in Orders is a primary key autoincrement, then the following should work:
SELECT c.id,
c.name,
COALESCE(t1.price, 0.0) AS price,
COALESCE(t1.product, 'NA') AS product
FROM Customers c
LEFT JOIN Orders t1
ON c.id = t1.person_id
LEFT JOIN
(
SELECT person_id, MAX(CAST(SUBSTRING(id, 4, LEN(id)) AS INT)) AS max_id
FROM Orders
GROUP BY person_id
) t2
ON t1.person_id = t2.person_id AND
t2.max_id = CAST(SUBSTRING(t1.id, 4, LEN(t1.id)) AS INT)
This answer assumes that taking the greatest order ID per customer will yield the most recent purchase. Ideally you should have a timestamp column which captures when a transaction took place. Note that even in the query above, we still have no way of knowing when the most recent transaction took place.
So where is the timestamp column? It's not mentioned in your table schema. But your description does not mention the status column either, and that is clearly in there.
Is orders.id unique? Is it the key for the Orders table?> If it is, then your schema has no way to identify "duplicate" records. You cannot mean to imply that only one order per customer is allowed, so if there are multiple orders for a single customer, how do we identify the duplicates? By the unmentioned timestamp column?
If there IS a `timestamp column, and that's how you would identify dupes, then use it.
SELECT C.Id,C.Name, O.item, O.price, O.product
FROM Customers C LEFT JOIN Orders o
on o.id = (Select Min(id) from orders
where person_id = c.Id
and timestamp = o.timestamp
and status = 'Pending')
I am using MS Access 2013.
I am trying to selecting the number and name from Salesperson table. Number, name and postcode from Customers table as well as all the information from the CarSale table all within the past month and order by salesperson no.
I have come up with the following
SELECT CS.carNo, CS.dateOfSale, SA.salespersonNo, SA.name AS SalesName,
CU.customerNo, CU.name AS CustName, CU.postCode
FROM CarSale AS CS, Car AS C, Salesperson AS SA, Customer AS CU
WHERE CS.carNo = C.carNo AND CS.salespersonNo = SA.salespersonNo
AND CS.customerNo = CU.customerNo AND dateOfSale BETWEEN #01/09/2016#
AND #02/09/2016#
ORDER BY CS.salespersonNo;
However as you can see, this is butt-ugly! I did some research and found that I should be using "JOINS" so I went ahead and included them, this is where my problem starts.
After inserting the JOINS into the query I get something that looks like this:
SELECT CS.carNo, CS.dateOfSale, SA.salespersonNo, SA.name AS SalesName,
CU.customerNo, CU.name AS CustName, CU.postCode
FROM CarSale AS CS
JOIN Car AS C ON CS.carNo = C.carNo
JOIN Salesperson AS SA on CS.salespersonNo = SA.salespersonNo
JOIN Customer AS CU ON CS.customerNo = CU.customerNo
WHERE cs.dateOfSale BETWEEN #01/09/2016# AND #02/09/2016#
ORDER BY CS.salespersonNo;
Here are the tables:
**CarSale**
carNo salespersonNo customerNo dateOfSale
-------------------------------------------------------
**Salesperson**
salespersonNo name contactNo monthlySalary centreNo
--------------------------------------------------------------
**Customer**
customerNo name contactNo postCode
---------------------------------------------
The error I am getting is "Syntax error in FROM clause."
I think you're close, but there is something wonky about your JOINs - you have a join on 'Car', but that's not one of your tables. JOINing occurs between tables, with ON specifying the fields that are equivalent (what you are JOINing ON). With that in mind:
SELECT s.salespersonNo, s.name, c.customerNo, cs.carNo,
cs.dateofsale, c.name, c.postCode
FROM salesperson s
INNER JOIN carsale cs
ON cs.salespersonNo = s.salespersonNo
INNER JOIN customer c
ON cs.customerNo = c.customerNo
WHERE cs.dateOfSale BETWEEN #01/09/2016# AND #02/09/2016#
ORDER BY CS.salespersonNo;
Notice that your WHERE and ORDER BY are unchanged, and I just used different aliases in my test run. The main difference is in the JOIN - I join from salesperson to CarSales ON the salespersonNo, and then from CarSales to customerNo, similar to what you already have.
The syntax error is because with multiple JOINs you need parentheses around every pair of them.
It would be a lot easier to use the query designer, it does those things automatically.
SELECT CS.carNo, CS.dateOfSale, SA.salespersonNo, SA.name AS SalesName,
CU.customerNo, CU.name AS CustName, CU.postCode
FROM (((CarSale AS CS
INNER JOIN Car AS C ON CS.carNo = C.carNo)
INNER JOIN Salesperson AS SA on CS.salespersonNo = SA.salespersonNo)
INNER JOIN Customer AS CU ON CS.customerNo = CU.customerNo)
WHERE cs.dateOfSale BETWEEN #01/09/2016# AND #02/09/2016#
ORDER BY CS.salespersonNo;
As Stidgeon wrote, if these are all fields you need, you can omit the join with Car.