Schema is frightening. Many-to-many on customers-loans? Many-to-many on customers-accounts? Why?? Employees has a branchname
column instead of an FK relationship to branches
. loan_operations
has FK to employees
!? I don't mean to stray from the topic or sound flippant, but there are so many anti-patterns here I don't even know where to begin. But I will try to help with the specific question anyway.
Q1:
CREATE PROCEDURE GetBranchSummaryByCity
@City varchar(50)
AS
SELECT
b.id, b.address, b.name, b.assets,
b2.EmployeeCount, b2.CustomerCount,
b2.TotalLoanAmount, b2.TotalAccountBalance
FROM branches b
INNER JOIN
(
SELECT
b.id,
ISNULL(COUNT(DISTINCT e.id), 0) AS EmployeeCount,
ISNULL(COUNT(c.id), 0) AS CustomerCount,
ISNULL(SUM(l.amount), 0) AS TotalLoanAmount,
ISNULL(SUM(a.balance), 0) AS TotalAccountBalance
FROM branches b
LEFT JOIN employees e
-- Fix your schema so this matches the branch ID instead!
ON e.branchname = b.name
LEFT JOIN employee_customer ec
ON ec.employeeid = e.id
LEFT JOIN customers c
ON c.id = ec.customerid
LEFT JOIN customer_accounts ca
ON ca.customerid = c.id
LEFT JOIN accounts a
ON a.id = ca.accountid
LEFT JOIN loan_customer lc
ON lc.customerid = c.id
LEFT JOIN loans l
ON l.id = lc.loanid
WHERE b.Name LIKE '%' + @City + '%'
GROUP BY b.id
) b2
ON b2.id = b.id
I'll note that you have an amount
column in both loans
and loan_operations
. It's hard to know what the difference is between these two - it's entirely possible that loans
shouldn't have this column at all, and instead it should be summed from the column in loan_operations
.
Q2:
CREATE PROCEDURE FindCustomersWithLoansByDateRange
@BeginDate datetime,
@EndDate datetime
AS
SELECT c2.id, c2.name, c2.address, ...
FROM
(
SELECT DISTINCT c.id
FROM customers c
INNER JOIN loan_customer lc
ON lc.customerid = c.id
INNER JOIN loans l
ON l.id = lc.loanid
INNER JOIN loan_operations lo
ON lo.loanid = l.id
WHERE lo.date BETWEEN @BeginDate AND @EndDate
) c1
INNER JOIN customers c2
ON c2.id = c1.id
Q3:
CREATE PROCEDURE GetEmployeeServiceSummaryByDateRange
@BeginDate datetime,
@EndDate datetime
AS
SELECT e.id, ISNULL(es.CustomerCount, 0) AS CustomerCount, e.name, e.position, ...
FROM employees e
LEFT JOIN
(
SELECT e.id, COUNT(DISTINCT c.id) AS CustomerCount
FROM employees e
INNER JOIN employee_customer ec
ON ec.employeeid = e.id
INNER JOIN customers c
ON c.id = ec.customerid
INNER JOIN loan_customer lc
ON lc.customerid = c.id
INNER JOIN loans l
ON l.id = lc.loanid
INNER JOIN loan_operations lo
ON lo.loanid = l.id
WHERE lo.date BETWEEN @BeginDate AND @EndDate
GROUP BY e.id
) es
ON es.id = e.id