Need help creating a query for a non-normalized database - sql-server

I've never worked with a non-normalized database before, so I'll try and explain my problem as best I can. So I have two tables:
The customers table holds all the customers information, and the orders table holds all the orders that they have placed. I haven't listed all the fields in the tables, just the ones that I need. The customer number in both tables is not the primary key, but I'm inner joining on them anyway. So the problem I'm having is that I don't know how to make a query that:
Selects all the customers with their first name, last name, and email, and also show the most recent orderdate, most recent total, and most recent ordertype. I know that I have to use a max() aggregate for the date, but that's as far as I got. Please help a noob out.

You can try:
SELECT FirstName,
LastName,
Email,
OrderDate,
OrderTotal,
OrderType
FROM Customers AS C
INNER JOIN Order AS O
ON O.CustomerNumber = C.CustomerNumber AND
O.OrderDate = (
SELECT MAX (O1.OrderDate)
FROM Order AS O1
WHERE O1.CustomerNumber = C.CustomerNumber)
)

assuming that Orders.OrderDate is unique for each CustomerNumber, does this work for you? if a single CustomerNumber has more than one entry in Order for OrderDate, you'll get each of those rows.
select c.FirstName, c.LastName, c.Email, o.OrderDate, o.OrderTotal, o.OrderType
from Customers c
join
(select CusomterNumber, max(OrderDate) as MostRecentOrderDate
from Orders
group by CustomerNumber
) mro on mro.CustomerNumber=s.CustomerNumber
join Orders o on o.OrderDate=mro.MostRecentOrdeDate and
o.CustomerNumber=mro.CustomerNumber

Try this:
SELECT
Customers.*, Orders.*
FROM
Customers
JOIN
(SELECT
Customer_Number,
MAX(Order_Date) OrderDate
FROM
Orders
GROUP BY
Customer_Number
) as Ord ON Customers.Customer_Number = Ord.Customer_Number
JOIN Order ON Orders.Customer_Number = Ord.Customer_Number

If you are doing this with SQL Server use the query designer and basically all you want to do is do a join since you have two keys that are the same one in Customer Table ->Customer Join on Order->Customer alias the Customer table as C and Orders table as O
so for example
SELECT Customer.*, Orders.*
From Customer c, Orders O INNER JOIN O where C.Customer Number = O.Customer Number
This should be enough to get you started.. if you don't want all the fields then fully qualify the names for example
SELECT C.FirstName, C.LastName, O.OrderDate, O.OrderType FROM Customer C, Orders O
WHERE C.Customer NUmber = O.Customer Number //this is another way of doing a Join when working with the where Clause.

Related

SQL Project using a where clause

So this is what I am working with new to sql and still learning been stuck on this for a few days now. Any advice would be appreciated I attached the image of the goal I'm trying to achieve
OrderItem And Product Table
Order And OrderItem Table(https://i.stack.imgur.com/pdbMT.png)
Scenario: Our boss would like to see the OrderNumber, OrderDate, Product Name, UnitPrice and Quantity for products that have TotalAmounts larger than the average
Create a query with a subquery in the WHERE clause. OrderNumber, OrderDate and TotalAmount come from the Order table. ProductName comes from the Product table. UnitPrice and Quantity come from the OrderItem table.
This is the code I came up with but it causes product name to run endlessly and displays wrong info.
USE TestCorp;
SELECT DISTINCT OrderNumber,
OrderDate,
ProductName,
i.UnitPrice,
Quantity,
TotalAmount
FROM [Order], Product
JOIN OrderItem i ON Product.UnitPrice = i.UnitPrice
WHERE TotalAmount < ( SELECT AVG(TotalAmount)
FROM [Order]
)
ORDER BY TotalAmount DESC;
Best guess assuming joins and fields not provided.
SELECT O.OrderNumber, O.orderDate, P.ProductName, OI.UnitPrice, OI.Quantity, O.TotalAmount
FROM [Order] O
INNER JOIN OrderItem OI
on O.ID = OI.orderID
INNER JOIN Product P
on P.ID= OI.ProductID
CROSS JOIN (SELECT avg(TotalAmount) AvgTotalAmount FROM [Order]) z
WHERE O.TotalAmount > z.AvgTotalAmount
Notes:
You're mixing join notations don't use , and inner join together that's mixing something called ANSI Standards.
I'm not sure why you have a cross join to product to begin with
You don't specify how to join Order to order item.
It seems very odd to be joining on Price.... join on order ID or productID maybe?
you could cross join to an "Average" result so it's available on every record. (I aliased this inline view "Z" in my attempt)
so what the above does is include all Orders. and for each order, an order item must be associated for it to be included. And then for each order item, a productid must be included and related to a record in product. If for some reason an order item record doens't have a related entry in product table, it gets excluded.
I use a cross join to get the average as it's executed 1 time and applied/joined to every record.
If we use the query in the where clause it's executed one time for EVERY record (unless the DB Engine optimizer figures it out and generates a better plan)
I Assume
Order.ID relates to OrderItem.OrderID
OrderItem.productID relates to Product.ID
Order.TotalAmount is what we are wanting to "Average" and compare against
Every Order has an Order Item entry
Every Order Item entry has a related product.

Insert Into TABLE from 3 separate tables

I am getting my face kicked in....
I have a total of 4 tables
1. Business (BusinessID, CustomerID, BusName, Territory)
2. Customer (CustomerID, Name)
3. Sales (BusinessID, CustomerID, Territory, Jan, Feb, Mar, Apr, May, Jun)
4. Performance (this is the table I want the info in)
I've already created the table to have the following columns, BusinessID, CustomerID, BusName, Name, Territory, Jan,Feb,Mar,Apr,May,Jun
Every time I try to insert its not properly joining and I am getting a bunch of errors "multi-part identifier could not be bound"
insert into Performance (BusinessID, CustomerID, BusName, Name, Territory, January2018, February2018, March2018, April2018, May2018, June2018)
select Business.BusinessID, Customer.CustomerID, Business.BusName, Customer.Name, Sales.Territory, Sales.January2018, Sales.February2018, Sales.March2018, Sales.April2018, Sales.May2018, Sales.June2018
from Business A
inner join Customer B ON a.CustomerID = b.CustomerID
inner join Sales C ON b.CustomerID = c.CustomerID;
Due to this error I had to do 3 seperate insert into and that caused a bunch of nulls....
face palm is happening and could use some advice.
Image: enter image description here
Thanks,
VeryNew2SQL
You have used table ALIASES, so you have to use those aliases in you SELECT
A for Business, B for Customer and C for Sales.
Read about ALIASES here.
select A.BusinessID, B.CustomerID, A.BusName, B.Name, C.Territory, C.January2018, C.February2018, C.March2018, C.April2018, C.May2018, C.June2018
from Business A
inner join Customer B ON a.CustomerID = b.CustomerID
inner join Sales C ON b.CustomerID = c.CustomerID;
When you create a table alias in your FROM and JOIN clauses, you need to refer to the aliases in your SELECT statement and not the actual table names.
Alternatively, leave your SELECT statement as it is, and adjust your table names to remove the alias. You'll then need the join conditions to refer to your actual table names, rather than the alias. So for example;
select Business.BusinessID, Customer.CustomerID, Business.BusName, Customer.Name, Sales.Territory, Sales.January2018, Sales.February2018, Sales.March2018, Sales.April2018, Sales.May2018, Sales.June2018
from Business
inner join Customer ON Business.CustomerID = Customer.CustomerID
inner join Sales ON Customer.CustomerID = Sales.CustomerID;
Even just try running the SELECT statement above first to make sure you get the query correct before trying it in your insert.

SQL Join using multiple tables

I'm using the version of SQL Server which comes with Visual Studio 2017 and trying to create a view by joining columns from four tables which are as follows:
Table1: Employee (EmpID, EmpName, EmpContact, EmpSalary)
Table2: Customer (CustID, CustName, CustContact, CustEmail)
Table3: Orders (OrderID, OrderCustID, OrderDate, OrderStatus, OrderValue)
Orders.OrderCustID is foreign key which relates to Customer.CustID
Table4: Job (JobID, JobOrderID, JobEmpID, JobStatus, JobRemarks)
Job.JobOrderID and Job.JobEmpID are two foreign keys which relate to Orders.OrderID and Employee.EmpID respectively.
Now, I want to perform a join which will show all records of Orders table along with matches from other tables in following order:
OrderID, JobStatus, OrderStatus, CustID, CustName, CustContact, CustDue, EmpID, EmpName, EmpContact, Oredrvalue
Someone please help me write the SQL Query to perform the join. Many thanks in advance.
You need to walk through each JOIN to figure out what to join where. In other words, how do you get from Employees to Customers? It's just a logical walk-through.
Here's one approach, using inner joins (basically a big intersection of sets).
SELECT OrderID, JobStatus, OrderStatus, CustID, CustName, CustContact, CustDue, EmpID, EmpName, EmpContact, OrderValue
FROM Job
INNER JOIN Orders
ON Orders.OrderId=Job.JobOrderID
INNER JOIN Customer
ON Customer.CustId=Orders.OrderCustId
INNER JOIN Employee
ON Employee.EmpId=Job.JobEmpID
OK, I figured it out and I'm posting it here for any future reference.
SELECT o.OrderID, j.JobStatus, o.OrderStatus, c.CustID, c.CustName, c.CustContact, c.CustDue, e.EmpID, e.EmpName, e.EmpContact, o.Oredrvalue
FROM Orders o
LEFT JOIN Customer c
ON o.OrderCustID=c.CustID
LEFT JOIN Job j
ON o.OrderID=j.JobOrderID
LEFT JOIN Employee e
ON j.JobEmpID=e.EmpID
I performed left join on all occasions because I need all the records from Orders table. Thanks a lot to all who responded.

How to do sub-query correctly while selecting two tables in Oracle?

I need to do a sub-query from a table to find all employees working in the same department that is part of the same city, but I'm not getting it.
I have the following tables:
Table departments
DEPARTMENTS
department_id
department_name
location_id
Table locations
LOCATIONS
location_id
street_address
postal_code
city
state_province
country_id
Table employees
EMPLOYEES
employee_id
first_name
last_name
email
phone_number
hire_date
job_id
department_id
My code right now is something like that :
SELECT
firt_name,
department_id,
job_id
FROM employees
WHERE state_province = (SELECT state_province FROM locations
WHERE state_province = 'Sao Paulo');
The problem is that while I want to select state_province from the table locations, I can't select the name, department id and job id from the table employees. How can I select both tables while doing the sub-query ?
Anyway, sorry if I did something wrong in the code, I am new to sub-queries.
You could try doing a join between the two tables instead:
SELECT
e.firt_name,
e.department_id,
e.job_id,
l.* -- replace with columns you really want
FROM employees e
INNER JOIN locations l
ON e.state_province = l.state_province
WHERE
e.state_province = 'Sao Paulo';
I don't know which columns you want to select from locations, but it doesn't really make sense to do a join just for state_province alone, as the employees table already has this column. So I just included location.* as a placeholder which you can replace with the columns you actually want.
Edit:
A join is the way to go here IMO, but if you absolutely need to use a subquery, then you can move your current subquery from the WHERE clause to the SELECT clause:
SELECT
firt_name,
department_id,
job_id,
(SELECT l.state_province FROM locations l
WHERE e.state_province = l.state_province) state_province
FROM employees e;
Note that this will only work if there is one matching province. For this and performance reasons, my join query is probably what you would want to use in practice.
I think in your case, sub-query may not be necessary.
A join table can do the trick.
SELECT e.first_name, e.department_id, e.job_id, l.state_province
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
LEFT JOIN locations l ON d.location_id = l.location_id
WHERE l.state_province = 'Sao Paulo';

SQL: Summing columns with a similar column in common

I'm extremely new to SQL Sever and so I apologize if the question is worded strange. I am doing a homework assignment, and this is the question:
"A manager wants to know the email address, number or orders, and the total amount of purchases made by each customer. Create a summary query that returns these three items for each customer that has orders."
I have all of the data queried, the problem is when I pull data from each customer, it will show the quantity of items per order, and I need the items to be pooled together into one column. This is my query thus far (again, total noob, please excuse any poor syntax, etc.)
SELECT EmailAddress,
ItemPrice - DiscountAmount * Quantity AS TotalPurchaseAmount,
COUNT(*) AS OrderQty
FROM Customers
JOIN Orders ON Customers.CustomerID = Orders.CustomerID
JOIN OrderItems ON Orders.OrderID = OrderItems.OrderID
GROUP BY Orders.CustomerID,
OrderItems.ItemPrice, OrderItems.DiscountAmount,
OrderItems.Quantity,
Customers.EmailAddress;
The following is a small bit of the result set that I get:
Email Address OrderTotal OrderQty
allan.sherwood#yahoo.com 253.15 2
allan.sherwood#yahoo.com 839.30 2
allan.sherwood#yahoo.com 1208.16 2
barryz#gmail.com 303.79 4
christineb#solarone.com 479.60 2
david.goldstein#hotmail.com 299.00 2
david.goldstein#hotmail.com 489.30 1
david.goldstein#hotmail.com 479.60 1
So as you can see, I have several orders I need to smoosh together into one single row per e-mail, I have looked and looked for an answer but the only thing I can find is how to find duplicates and ignore them, not combine their data. Any help is extremely appreciate, thanks so much for taking the time to read this :) If my question doesn't make sense please let me know so I can clear up any bad wording I may have used!
Just do GROUP BY CustomerID, EmailAddress:
SELECT
c.EmailAddress,
SUM((i.ItemPrice - i.DiscountAmount) * Quantity) AS TotalPurchaseAmount,
COUNT(*) AS OrderQty
FROM Customers c
INNER JOIN Orders o
ON c.CustomerID = o.CustomerID
INNER JOIN OrderItems i
ON o.OrderID = i.OrderID
GROUP BY
c.CustomerID, c.EmailAddress
Additional note: Use aliases for your tables
You need to change your formula and remove columns that you dont want to group by from select query..
for example your query should be something like this
SELECT EmailAddress,
--do your aggregation here
blah AS TotalPurchaseAmount,
COUNT(*) AS OrderQty
FROM Customers
JOIN Orders ON Customers.CustomerID = Orders.CustomerID
JOIN OrderItems ON Orders.OrderID = OrderItems.OrderID
GROUP BY Orders.CustomerID,
Customers.EmailAddress;

Resources