I need help to solve this exercise with SQL Server - sql

I'm working with AdventureWorks Database. And this is the schema of the Database (https://i.stack.imgur.com/iWJxh.gif).
The exercise statement:
Do a report for the last week with following details.
OrderDate
Sales Person Name
SalesID
Customer Person Name
Quantity of products selled
Quantity of distinct products selled
Total Amount of the sale
Credit Card type used for pay
If sales had a special offer
Paying attention to the following statements:
Take the last 7 days for which you have sales data.
Do not show sales that were paid with cards of the type "ColonialVoice".
Dates should be displayed in "DD/MM/YYYY" format.
The report be ordered by Date, descending.
There should not be two rows with the same sale id in the report.
I try with this code and the results that it gives me are only for some dates, and if you pay attention it only brings me the first day of each month only
SELECT
SOH.OrderDate AS 'Fecha_Venta',
PERSONASVendedor.FirstName + ' ' + PERSONASVendedor.LastName AS 'Nombre_Vendedor',
SOH.SalesOrderID AS 'ID_Venta',
PERSONASCliente.FirstName + ' ' + PERSONASCliente.LastName AS 'Nombre_Cliente',
SUM(SOD.OrderQty) AS 'Cantidad_Productos_Vendidos',
COUNT(DISTINCT SOD.ProductID) AS 'Productos_Distintos_Vendidos',
SUM(SOD.LineTotal) AS 'Monto_Total',
TARJETA.CardType AS 'Tarjeta',
CASE WHEN SOD.SpecialOfferID <> 1 THEN 'Si' ELSE 'No' END AS 'Ventas_Con_Ofertas'
FROM Sales.SalesOrderHeader SOH
INNER JOIN Sales.SalesPerson ON SOH.SalesPersonID = Sales.SalesPerson.BusinessEntityID
INNER JOIN Sales.Customer ON SOH.CustomerID = Sales.Customer.CustomerID
INNER JOIN Person.Person PERSONASVendedor ON Sales.SalesPerson.BusinessEntityID = PERSONASVendedor.BusinessEntityID
INNER JOIN Person.Person PERSONASCliente ON Sales.Customer.PersonID = PERSONASCliente.BusinessEntityID
INNER JOIN Sales.SalesOrderDetail SOD ON SOH.SalesOrderID = SOD.SalesOrderID
INNER JOIN Sales.CreditCard TARJETA ON SOH.CreditCardID = TARJETA.CreditCardID
WHERE TARJETA.CardType <> 'ColonialVoice'
GROUP BY SOH.OrderDate, SOH.SalesOrderID, PERSONASVendedor.FirstName, PERSONASVendedor.LastName, PERSONASCliente.FirstName, PERSONASCliente.LastName, TARJETA.CardType, SOD.SpecialOfferID
ORDER BY SOH.OrderDate DESC
How can I solve this problem?
I would be missing to do some statements too.
Results obtained

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!

How to get the Total Amount Each Customer Has Spent

I am making a database for a simple purchase, customer, employee, etc tables.
I am making a query that includes all of the employees who have boughten something, along with some of their data, and then the last field is supposed to have the total amount that they have boughten. However, I am not too sure on how to achieve this.
I am not quite sure on how to get the total to be almost like a sub-query to total up what the customer has gotten. For instance, the first 5 rows should have a total of 180.40.
I have been looking online for some help with totaling queries but couldn't find any good examples.
Any help would be wonderful! Thank you (I am pretty new to SQL and Access)!
Edit: Forgot to add this!
SELECT Employee.FirstName, Employee.LastName, Purchase.PurchaseID, Product.ProductName, Product.Price, Product.Price AS Total
FROM Employee
INNER JOIN (Customer INNER JOIN (Product INNER JOIN Purchase ON Product.ProductID = Purchase.ProductID)
ON Customer.CustomerID = Purchase.CustomerID) ON Employee.EmployeeID = Customer.EmployeeID;
Do you just want aggregation?
SELECT e.FirstName, e.LastName,
SUM(p.Price)
FROM ((Employee as e INNER JOIN
Customer as c
ON e.EmployeeID = c.EmployeeID
) INNER JOIN
Purchase pu
ON c.CustomerID = pu.CustomerID
) INNER JOIN
Product as p
ON p.ProductID = pu.ProductID
GROUP BY e.FirstName, e.LastName;

Joining 2 Many-To-Many Relationship Tables

Problem:
Find the net balance of the total order amount and total payments for each customer.
There are 4 tables involved: OrderDetails, Orders, Payments and Customer.
The total amount order = quantity order * price each [in OrderDetails]
The total payment = sum of different payments for the same order.
Customers are linked to Payments and Orders with CustomerNumber. Orders are linked to OrderDetails with OrderNumber.
I tried joining the 4 tables with the INNER JOIN function.
SELECT
c.customername,
SUM(od.quantityordered * od.priceeach) - SUM(p.amount) AS Net_Balance
FROM
(
(
orderdetails od
INNER JOIN orders o ON od.ordernumber = o.ordernumber
)
INNER JOIN customers c ON o.customernumber = c.customernumber
)
INNER JOIN payments p ON c.customernumber = p.customernumber
GROUP BY c.customername;
The expected results should be 0 for almost every customers.
However, what I have got is the total amount order and total payment are multiplied by some constants. Specifically, the total payment shown is multiplied by the number of payments for each order.
Anybody have any ideas to save my life?
This is a typical issue when dealing with N-M relationships. To solve it, one solution is to move the aggregation to subqueries:
SELECT c.customername, o.amt - p.amt AS Net_Balance
FROM customers c
INNER JOIN (
SELECT ord.customernumber, SUM(det.quantityordered * det.priceeach) as amt
FROM orders ord
INNER JOIN orderdetails det ON ord.ordernumber = det.ordernumber
GROUP BY ord.customernumber
) o ON o.customernumber = c.customernumber
INNER JOIN (
SELECT customernumber, SUM(amount) as amt
FROM payments
GROUP BY customernumber
) p ON p.customernumber = c.customernumber
SELECT c.customername, SUM(od.quantityordered*od.priceeach) as ordersum , SUM(p.amount) as paymentsum'
What's the result of the two columns ?
Is it what you want?

SQL-Server, confront Customers with Employees function

I might have a really simple question, but it doesn't seem i can find the solution yet. Basically, i have to write a SQL-Server function, based on Northwind DB. It has to:
Take 2 dates as arguments and display, without repetition these Customer's data ID | Name | City | Address , for those customers where the total purchase he had made from at least one Employee , is greater than the average sale made by this Employee between the two dates.
So the main steps should be:
1. Retrieve the total purchase made from a Customer from each Employee. I know how to get the total purchase from each Company:
SELECT
Customers.CompanyName, SUM(UnitPrice*Quantity)
FROM Orders inner join [Order Details]
ON Orders.OrderID=[Order Details].OrderID INNER JOIN
Customers ON Orders.CustomerID=Customers.CustomerID
GROUP BY Customers.CompanyName
But how can i get those made from each employee?
2.Confront this with the average sales of this Employee between the given dates. I can get the average for each employee:
SELECT FirstName+' '+LastName, AVG(UnitPrice*Quantity)
FROM Orders inner join [Order Details]
ON Orders.OrderID=[Order Details].OrderID
INNER JOIN Employees
ON Orders.EmployeeID=Employees.EmployeeID
WHERE OrderDate BETWEEN #dt1 and #dt2
GROUP BY FirstName+' '+LastName
Note that i'm only pasting the query part, but here, the Employee should depend on the first query (probably this should be put inside a subquery)
Everything should be put inside a single function (it should not be split in two). The Northwind DB diagram is: Northwind Diagram . Please help!
Hope I got the logic right:
create function x (#from datetime, #to datetime)
returns table
as
return (
with cust as (
select o.customerid, o.employeeid, sum(unitprice*quantity) as cust_purchase
from orders o
inner join [order details] d on o.orderid=d.orderid
where o.orderdate between #from and #to
group by o.customerid, o.employeeid
),
emp as (
select o.employeeid, avg(unitprice*quantity) as emp_sale
from orders o
inner join [order details] d on o.orderid=d.orderid
where o.orderdate between #from and #to
group by o.employeeid
)
select c.customerid, c.companyname, c.city, c.address
from cust
inner join emp on cust.employeeid = emp.employeeid
and cust.cust_purchase > emp.emp_sale
inner join customers c on cust.customerid = c.customerid
)
go
select * from x ('19980401', '19980430')

Query very slow with LEFT AND RIGHT JOIN - SQL Server CE

I need to query the payment records with between date. The payment table has relation with invoice table while the invoice table has relation with customer table. So all the payment records must be shown even the invoice or the customer record already deleted.
To get less than 50 rows with 1 month period, it will take time more than 1 minutes. Any ideas how to reduce the times?
Here my snippet code :
SELECT
C.name, I.id as id, P.amount, P.date
FROM
tbl_customer C
LEFT JOIN
tbl_inv I ON C.id = I.id_customer
RIGHT JOIN
tbl_payment P ON I.id = P.id_invoice
WHERE
P.date >= '20131201' AND P.date <= '20140101'
ORDER BY
P.date;