SQL Server : complex Joins for reporting - sql-server

I am writing a query for a banking scenario. The query lists the number of employees working, the amount of customers served, the total loan amount, and the total account amount at a particular bank branch.
The tables are designed like this:
Every branch has employees assigned to it, every bank account is assigned to a branch, every loan is assigned to a branch. A customer can have both a loan and an account at the same branch but should only count as 1 customer served. A customer can have accounts/loans at different banks and should count customer as one customer per bank.
The desired output would look like:
I honestly have no idea where to start and any help will be greatly appreciated. Thanks for taking the time to read this!

Let me know if this works:
SELECT b.BranchID BranchID,
COUNT(e.empID) NumEmployees,
COUNT(c.customerID) NumCustomers,
SUM(ISNULL(l.balance,0)) [Total Load Amount],
SUM(ISNULL(a.balance,0)) [Total Account Amount]
FROM Branch b
JOIN Employee e ON b.branchID = e.branchid
JOIN Loan l ON l.branchID = b.branchID
AND l.empID = e.empID
JOIN Account a ON a.branchID = b.branchID
AND a.empID = e.empID
JOIN Customer c ON c.customerID = l.customerID
AND c.customerID = a.customerID
GROUP BY b.branchID

Related

Summing a total from multiple sales into a single column

I'm having issues with what I believe should be a simple problem in SQL Server 2017. I need to show the total sales price for a given sale. This is what I have written (note I deleted the totalprice sum formulae because it returned an error) :
USE [Antiques]
GO
DECLARE #TotalPrice INT
SELECT
Sales.SaleNo,
Sales.SalesDate,
Customers.FirstName,
Customers.LastName,
Products.Price,
#TotalPrice AS TotalPrice
FROM
Customers JOIN Sales ON Customers.CustomerID = Sales.CustomerID
JOIN SalesProducts ON Sales.SaleNo = SalesProducts.SaleNo
JOIN Products ON SalesProducts.ProductID = Products.ProductID
WHERE (Products.ProductID = SalesProducts.ProductID)
GO
This is the result:
Even if I remove the item price (which I have just put in temporarily and won't be in final code) there are still multiple lines per sale (1 for each item in the sale). Have I used the wrong joins? How can I get it looking like this:
Can anyone please tell me what I'm doing wrong? I've tried so many ways of using the Sum function and Group By and failing. (Note: this has to be a basic query and not a stored procedure unfortunately)
Actually you're not too far away. I'd move the grouping in a derived table and join that, to get the totalprice.
SELECT sales.saleno,
sales.salesdate,
customers.firstname,
customers.lastname,
x.totalprice
FROM sales
INNER JOIN customers
ON customers.customerid = sales.customerid
INNER JOIN (SELECT salesproducts.saleno,
sum(products.price) totalprice
FROM salesproducts
INNER JOIN products
ON products.productid = salesproducts.productid
GROUP BY salesproducts.saleno) x
ON x.saleno = sales.salesno;

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: 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;

Selecting Top Seller from Dealers Table with count of sales

First off I have Agents and each Agent can have dealer(s). I have an agent table containing all of my agents. I have a contracts table where all of the sales are listed. And I have a dealer table that attaches all of the dealers to agents.
SELECT a.agent_name, COUNT(distinct c.dealer_number) as '# of Selling Dealers'
FROM agents a
inner join contracts c on c.agent_number = a.agent_number
inner join dealers d on d.agent_number = a.agent_number
group by agent_name
For example this query if I ran it right now would return
Agent Name # of selling Dealers
Agent #1 6
What I now need to figure out is who is the top seller and how much they sold. This info would be in the contracts table.
So as in the example Agent #1 has 6 dealers who have made sales. Lets pretend Dealer #5 of that list has the most sales.
So it should return as follows:
Agent Name # of selling Dealers Top Dealer Volume
Agent #1 6 Dealer #5 24
I would like to return the dealer_name of the top seller and how many sales they got (also in the contracts table).
Additional Info
Each line in the contracts table counts as a sale. It will have a dealer_name, dealer_number and agent_name, agent_number
agents table has agent_name, agent_number
dealers table has dealer_name, dealer_number, agent_number
contracts table has agent_number, dealer_number
try
SELECT
m.agent_name,
max_dealer_contract_sales,
dealer_name
FROM
(SELECT
agent_name,
MAX(dealer_contract_sales) AS max_dealer_contract_sales
FROM
(SELECT
agent_name,
dealer_name,
COUNT(dealer_name) AS dealer_contract_sales
FROM
contracts
GROUP BY
agent_name,
dealer_name) c
GROUP BY
agent_name) m INNER JOIN
(SELECT
agent_name,
dealer_name,
COUNT(dealer_name) AS dealer_contract_sales
FROM
contracts
GROUP BY
agent_name,
dealer_name) c ON
m.agent_name = c.agent_name AND
max_dealer_contract_sales = dealer_contract_sales
;with AgentPerformance as
(
SELECT agent_number, count(distinct c.dealer_number) as SellingDealers
FROM contracts
GROUP BY agent_number,
), DealerPerformance as
(
SELECT agent_number, dealer_number, count(*) DealerSalesCnt
FROM contracts
GROUP BY agent_number, dealer_number,
), TopDealersTmp as
(
SELECT agent_number, dealer_number, DealerSalesCnt,
row_number() over (partition by agent_number order by DealerSalesCnt desc) rn
FROM DealerPerformance
), TopDealers as
(
SELECT agent_number, dealer_number, DealerSalesCnt
FROM TopDealersTmp
WHERE rn = 1
)
SELECT a.agent_name, ap.SellingDealers, d.dealer_name, td.DealerSalesCnt
FROM AgentPerformance ap
join agents a
on ap.agent_number = a.agent_number
join TopDealers td
on ap.agent_number = td.agent_number
join dealers d
on d.dealer_number = td.dealer_number
In AgentPerformance I calculate amount of selling dealers.
In DealerPerformance I calculate how many sales every dealer has (to choose the best one later).
In TopDealersTmp I re-number dealers according to performance starting from top performers for each agent.
In TopDealers I select only top performers.
In final select I pull names by numbers and do output.

Prevent duplicates sql server

Ok, in this query I'm extracting information from 5 tables, the table Company, Programmer, Tester, Manager and the table Contract. I will extract the Programmers', testers', and Managers' Names and Telephone Numbers, as well as the Company they work on, and this company is responsible for managing this program as a request by x person doesn't matter.
Problem is with the code below, a certain information will come out as many times as there is other information, like a programmer's Name and Tel Number will come out as many times as there are Managers and Testers on the company.
I tried with left outer join and it would give me even more results, so how can I fix this so next time a result won't be duplicated but say NULL?
SELECT DISTINCT pg.name,
pg.Tel_Nr,
Mgr.name,
Mgr.Tel_Nr,
Ts.Name,
Ts.Tel_Nr,
Pg.Name,
con.program_name
FROM Company AS Cm
INNER JOIN Programmer AS Pg ON Pg.company = Cm.name
INNER JOIN Manager AS Mg ON Mg.company = Cm.name
INNER JOIN Tester AS Ts ON Ts.company = Cm.name
INNER JOIN Contract AS Con ON Con.program_name = 'My Program'
AND Cm.name = Con.Company
Surely it would make more sense to produce a list of contact details with perhaps a job description. Something like this:
WITH Cte as (select Cm.name from
Contract as Con join Company as Cm on Cm.name = Con.Company
where Con.program_name = 'My Program')
SELECT pg.name, pg.Tel_Nr, 'Programmer' as JobTitle
FROM Cte INNER JOIN
Programmer as Pg on Pg.company = Cte.name
UNION ALL
SELECT Mgr.name, Mgr.Tel_Nr,'Manager' as JobTitle
FROM Cte INNER JOIN
Manager as Mg on Mg.company= Cte.name
UNION ALL
SELECT Ts.Name, Ts.Tel_Nr, 'Tester' as JobTitle
FROM Cte INNER JOIN
Tester as Ts on Ts.company = Cte.name
This solution deploys a Common Table Expression (labelled Cte) to avoid querying thr Company and Contract tables multiple times. Find out more.

Resources