Subtract column data from two unrelated tables - sql

This is the database diagram I want to determine the blood that's remaining in each bank this achieved by subtracting [Amount Accepted] from [Amount Donated]
I have tried to make selections of blood drawn into banks and blood withdrawn from banks but my problem is I can't subtract the two columns [blood drawn] and [blood withdrawn] because they are in tables which are not related

You can try like following.
SELECT *, [blood drawn(ml)]-[blood withdrawn(ml)]
FROM
(
<YOUR QUERY1>
)A
INNER JOIN
(
<YOUR QUERY2>
)B
ON A.[Blood Bank Name]= B.[Blood Bank Name]

Wrap both Selects in Derived Tables or Common Table Expressions and join them, e.g.
with donated as
( select ...
)
, accepted as
( select ...
)
select ...
from donated as a
join accepted as a
on a.[blood bank name] = d..[blood bank name]

Note the '-' before [Amount Accepted] is the key.
SELECT x.[Blood Bank Name], SUM(x.[Net Amount])
FROM
(
SELECT [Blood Bank Name], [Amount Donated] AS [Net Amount]
FROM [Donation Record]
UNION ALL
SELECT [Blood Bank Name], -[Amount Accepted] AS [Net Amount]
FROM [Transfusion Record]
) x
GROUP BY x.[Blood Bank Name]

Related

Why does my record count increase as my denominator for a division performed in a nested query increases?

In my query I'm trying to calculate the total overtime worked by employees by dividing basic salary by 173(hours in a month) which gives me the hourly rate then dividing the total overtime amount of employee by the hourly rate. To my surprise the record count increases as the number of hours in a month increases, should it not decrease?
Here's my script:
select 'Employees that worked more overtime' [CAAT],*
from ( select H.[Month]
,H.[Employee Code]
,H.[Department]
,H.[Job title]
,H.[Surname]
,H.[Full Names]
,H.[Basic Salary]
,R.[Overtime]
,H.[Hourly Rate]
,round(R.[Overtime] / H.[Hourly Rate],2) [Overtime Hours]
from (select [Month]
,[Employee Code]
,Department
,[Job title]
,[Surname]
,[Full Names]
,nullif(convert(money,[Amount]),0.00) [Basic Salary]
,nullif(round(convert(money,[Amount]) / 173,2),0.00) [Hourly Rate]
from [Salary DB]
where [Field Desc] = 'ED01-Basic Salary') H
left join
(select [Month]
,[Employee Code]
,nullif(sum(convert(money,[Amount])),0.00) [Overtime]
from [Salary DB]
where [Field Desc] in ('ED02-O/Time 1.5','ED02-O/Time 2.0','ED42-Sunday Pay')
group by [Month]
,[Employee Code]) R
on H.[Employee Code] = R.[Employee Code]
and H.[Month] = R.[Month]) [Data]
where [Overtime Hours] > '40'
Order by [Employee Code], [Month] Desc

Calculate AVG in SQL Select statement when some values are NULL

I have struggled to find a solution to this problem, so any help would be hugely appreciated.
I have two tables, lets call one table_a and one table_b, representing two possible sources of customer orders. They both contain a field called "customer_number" which I am using to outer join table_b to table_a. I am then calculating an average customer order size given the two tables.
Where i struggle is where a customer has an entry in either table, but not in both. Then my average calc returns NULL.
Table_a:
Customer Number
Total Online Orders
123456789
1350
987654321
650
Table_b:
Customer Number
Total InStore Orders
123456789
350
So basically the second customer does not have an entry in table_b.
My code as follows:
select distinct
a.[customer number],
a.[Total Online Orders],
b.[Total InStore Orders],
coalesce(a.[Total Online Orders] + b.[Total InStore Orders]) / 2 as [Average Order Size]
from table_a a
full outer join table_b b on a.[customer number]=b.[customer number]
Results table:
Customer Number
Total Online Orders
Total InStore Orders
Average Order Size
123456789
1350
350
850
987654321
650
NULL
NULL
I basically want the results table to show 650 for customer 987654321. Any ideas what I am doing wrong?
thanks!
You can use the brute force method:
( coalesce(a.[Total Online Orders], 0) + coalesce(b.[Total InStore Orders], 0)) /
nullif(case when a.[Total Online Orders] is not null then 1 else 0 end +
case when b.[Total InStore Orders] is not null then 1 else 0 end, 0)
)
) as [Average Order Size]
Use COALESCE() for the values of the 2 columns twice:
(
coalesce(a.[Total Online Orders], b.[Total InStore Orders]) +
coalesce(b.[Total InStore Orders], a.[Total Online Orders])
) / 2 as [Average Order Size]
Consider UNION as well, which handles a few other cases too, especially where customer number isn't necessarily unique in each table:
WITH cte (xtype, [customer number], order_amt) AS (
select 1 AS xtype, [customer number], [Total Online Orders] FROM table_a UNION ALL
select 2 AS xtype, [customer number], [Total InStore Orders] FROM table_b
)
SELECT [customer number]
, SUM(CASE WHEN xtype = 1 THEN order_amt ELSE 0 END) AS [Total Online Orders]
, SUM(CASE WHEN xtype = 2 THEN order_amt ELSE 0 END) AS [Total InStore Orders]
, AVG(order_amt) AS [Average Order Size]
FROM cte
GROUP BY [customer number]
ORDER BY [customer number]
;

Access SQL SUM with subtraction

I am writing what I thought would be a relatively simple Access DB for a doctor client of mine who has a very small practice. I am having trouble with reporting a patient's balance.
I have 3 tables:
Patients (id, [First Name], [Last Name], {other cols})
Treatments (id, Fee, Patient_id, {other cols})
Payments (id, Amount, Patient_id, {other cols})
I want a query to simply show me the total fees for treatments, the total amount paid, and the current balance. I wrote the following...
Select
Patients.[Last Name],
Patients.[First Name],
SUM(select SUM(Treatments.Fee) from Treatments Where Treatments.Patient=#PatientID)
AS CHARGES,
SUM(select SUM(PAYMENTS.AMOUNT) from PAYMENTS Where PAYMENTS.Patient=#PatientID)
AS PAYMENTS,
SUM(
(select SUM(Treatments.Fee) from Treatments Where Treatments.Patient=#PatientID)
- (select SUM(PAYMENTS.AMOUNT) from PAYMENTS Where PAYMENTS.Patient=#PatientID)
)
as Balance
FROM Patients,Treatments,PAYMENTS
WHERE Patients.ID = #PatientID
GROUP BY Patients.[Last Name],Patients.[First Name]
The Charges and Payments columns work fine, but the Balance I'm given is weird. The below is based on:
5 treatment entries for this patient in the amounts, 50,25,35,45,125 (280).
3 payment entries in the amounts, 15,60,25 (100).
I expect:
Charges = $280, Payments = $100, Balance = $180
But I get:
Charges = $280, Payments = $100, Balance = $2,700
By using this FROM clause:
FROM Patients,Treatments,PAYMENTS
you're creating a Cartesian product.
Meaning your sum calculation for Balance will be multiplied by the number of records in each respective table (1 in Patients, 5 in Treatments, 3 in PAYMENTS):
15*total of fees- 15*total of payments = 15*280-15*100 = 4200-1500 =2700
You don't need Treatments and PAYMENTS in your FROM clause as you're doing your calculations in your sub query.
Use this statement instead:
Select
Patients.[Last Name],
Patients.[First Name],
SUM(select SUM(Treatments.Fee) from Treatments Where Treatments.Patient=#PatientID)
AS CHARGES,
SUM(select SUM(PAYMENTS.AMOUNT) from PAYMENTS Where PAYMENTS.Patient=#PatientID)
AS PAYMENTS,
SUM(
(select SUM(Treatments.Fee) from Treatments Where Treatments.Patient=#PatientID)
- (select SUM(PAYMENTS.AMOUNT) from PAYMENTS Where PAYMENTS.Patient=#PatientID)
)
as Balance
FROM Patients
WHERE Patients.ID = #PatientID
GROUP BY Patients.[Last Name],Patients.[First Name]
Select
Patients.[Last Name],
Patients.[First Name],
SUM( treatments.Fee)
AS CHARGES,
SUM(PAYMENTS.AMOUNT)
AS PAYMENTS,
SUM(Treatments.Fee)
- SUM(PAYMENTS.AMOUNT)
as Balance
FROM Patients a join Treatments b on a.id=b.patientid join PAYMENTS c on a.id=c.patientid
WHERE Patients.ID = #PatientID
GROUP BY Patients.[Last Name],Patients.[First Name]

how to select columns with aggregate function sql server

i need to select two columns.1. calculate sum of one column and display it 2.display column as it is. so i tried below code
SELECT Sum(CONVERT(FLOAT, Replace(total, Char(0), ''))) AS Total,
[product name]
FROM tb_sales_entry_each_product
GROUP BY [sales date]
error message
Column 'tb_sales_entry_each_product.Product Name' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
where i made error.thanks
just need to group
select SUM(CONVERT(float, REPLACE(Total, CHAR(0), ''))) as Total, [Product Name]
from tb_sales_entry_each_product group by [Sales Date], [product name]
When ever you do a numercial count sum etc, any other columns need to be grouped.
thats all your missing
Try this:
select SUM(CONVERT(float, REPLACE(Total, CHAR(0), ''))) as Total,
[Product Name] ,[Sales Date]
from tb_sales_entry_each_product
group by [Sales Date],[Product Name]

SQL Result Set Merge

I have a limitation where I can only send one result set to a reporting application at any one time, to produce an end report for a customer.
So a query like this
select
[AGENT],
[TRANSDATE],
[RECIPT NO],
[CUSTOMER NAME],
[ORDER NO] ,
[TRANS NO] ,
QUANTITY,
[AMOUNT COST],
From [Customer] C
However I need lots of totals at the bottom such as this query for some of the columns. I cannot make any changes to front end due to it being a legacy reporting application.
select
Sum ( QUANTITY ) as [SUM OF QUANTITY] ,
Sum ( AMOUNT COST ) AS [SUM OF AMOUNT COST]
From [Customer] C
Obviously I simplified the queries I am using. So the question is how to make 2 results sets one result set in SQL?
Union and union all failed due to date columns being defaulted if you use blank for a column in end application.
Rollup or Pivoting or CTE I kinda thought of but cannot see a solution yet.
what about windowed functions?
like...
select
[AGENT],
[TRANSDATE],
[RECIPT NO],
[CUSTOMER NAME],
[ORDER NO] ,
[TRANS NO] ,
QUANTITY,
[AMOUNT COST],
Sum ( QUANTITY ) over () as [SUM OF QUANTITY] ,
Sum ( [AMOUNT COST] ) over () AS [SUM OF AMOUNT COST]
From [Customer] C