Complex Calculation - SQL Server - sql

I'm currently working on calculating a larger set of data with a number of joins and the end result is a calculation across two tables. My current script looks like the following:
USE db1
Go
SELECT
customer, tb1.custid
FROM
[dbo].[tb1]
LEFT OUTER JOIN
[dbo].[tb2] ON tb1.custid = tb2.custid
LEFT OUTER JOIN
[dbo].[tb3] ON tb2.custnumber = tb3.custnumber
LEFT OUTER JOIN
[dbo].[tb4] ON tb2.custid = tb4.custid
WHERE
tb1.custclass = 'non-person'
AND tb4.zip IN ('11111', '11112')
GO
As you can see, it's not the cleanest, but it's working for gathering initial information. The reasoning for the number of joins is due to an incredibly odd table structure I did not create and the fact that the numerical data I need is only stored in tb3.
What I'm now trying to do is calculate the sum of 3 fields from tb3 that are all set as numeric fields and do an AND/OR comparison against a 4th field (also numeric). I know I can SUM them together, but I'm hoping for some input on three things:
Where to place that SUM calculation in the query?
Where to place and how to do the comparison of the SUM total against the 4th field?
Is it possible to return the higher of the two values to a TOTAL column in the initial SELECT?
Thank you in advance.

Where to place that SUM calculation in the query?
If you want it output, you probably want to just add it to the SELECT
SELECT
customer, tb1.custid
(tb3.col1 + tb3.col2 + tb3.col3) as Sum
FROM
...
Where to place and how to do the comparison of the SUM total against the 4th field?
You probably want to do this with a CASE statement, and this also answers your last question
Is it possible to return the higher of the two values to a TOTAL column in the initial SELECT?
SELECT
customer, tb1.custid
CASE WHEN (tb3.col1 + tb3.col2 + tb3.col3) > tb3.col4
THEN (tb3.col1 + tb3.col2 + tb3.col3)
ELSE tb3.col4
END as Total
FROM
...

You should be able to calculate the sum as a nested query:
SELECT (field1 + field2 + field3) AS fields_sum FROM tb3 (...)
Then in your main query you could do something like:
SELECT customer, tb1.custid, (CASE WHEN fields_sum > fourth_field THEN fields_sum ELSE fourth_field END) AS TOTAL (...)

Related

Alter a existing SQL statement, to give an additional column of data, but to not affect performance, so best approach

In this query, I want to add a new column, which gives the SUM of a.VolumetricCharge, but only where PremiseProviderBillings.BillingCategory = 'Water'. But i don't want to add it in the obvious place since that would limit the rows returned, I only want it to get the new column value
SELECT b.customerbillid,
-- Here i need SUM(a.VolumetricCharge) but where a.BillingCategory is equal to 'Water'
Sum(a.volumetriccharge) AS Volumetric,
Sum(a.fixedcharge) AS Fixed,
Sum(a.vat) AS VAT,
Sum(a.discount) + Sum(deferral) AS Discount,
Sum(Isnull(a.estimatedconsumption, 0)) AS Consumption,
Count_big(*) AS Records
FROM dbo.premiseproviderbillings AS a WITH (nolock)
LEFT JOIN dbo.premiseproviderbills AS b WITH (nolock)
ON a.premiseproviderbillid = b.premiseproviderbillid
-- Cannot add a where here since that would limit the results and change the output
GROUP BY b.customerbillid;
Bit of a tricky one, as what you're asking for will definitely affect performance (your asking SQL Server to do more work after all!).
However, we can add a column to your results which performs a conditional sum so that it does not affect the result of the other columns.
The answer lies in using a CASE expression!
Sum(
CASE
WHEN PremiseProviderBillings.BillingCategory = 'Water' THEN
a.volumetriccharge
ELSE
0
END
) AS WaterVolumetric

Question about divide result from the same column in SQL Server

I am trying to write statement in SQL Server. What I am trying to do is to get the result of count records in columns end with "R" divide the count of all the records. So it is basically the statement of a column with a statement " count (invoice) where Invoice like "%R" / count( Invoice)"
Here is my code without the divide calculation. I only come up with statement without the divide calculation.
SELECT
Invoice,
COUNT(ART_CURRENT__TRANSACTION.Invoice) AS Number_Revisions,
MAX(ART_CURRENT__TRANSACTION.[Customer]) AS "Customer",
MAX(ARM_MASTER__CUSTOMER.Name) AS "Name",
MAX(ART_CURRENT__TRANSACTION.[Job]) AS Job
FROM
ART_CURRENT__TRANSACTION
LEFT OUTER JOIN
ARM_MASTER__CUSTOMER ON ARM_MASTER__CUSTOMER.Customer = ART_CURRENT__TRANSACTION.Customer
WHERE
Invoice LIKE '%R'
GROUP BY
Invoice;
What I am trying to ask is how can I add a column that calculate the number of invoice end with "R"/ NUMBER OF INVOICE.
Thank you guys!
What I am trying to do is to get the result of count records in Columns end with "R" divide the count of all the records.
You seem to want this calculation:
SELECT AVG(CASE WHEN t.Invoice LIKE '%R' THEN 1.0 ELSE 0 END)
FROM ART_CURRENT__TRANSACTION t;
This assumes that invoice is in the transaction table. I don't think a join is necessary for what you want to do.

SQL Calculations over tables

There are 2 tables, there is an expected result, the result is to have the total cost of each engagement calculated, there are multiple tests taken during each engagement, each test ranges in cost (all set values), the expected result must be in terms of EngagementId, EngagementCost
The 2 tables, with there respective fields
- EngagementTest (EngagementId, TestId)
- Test (TestId, TestCost)
How would one go calculating the cost of each engagement.
This is as far as i managed to get
SELECT EngagementId, COUNT(TESTId)
FROM EngagementTest
GROUP BY EngagementId;
Try a SUM of the TestCost column rather than a COUNT. COUNT just tells you the number of rows. SUM adds up the values within the rows and gives you a total. Also your existing query doesn't actually use the table that contains the cost data. You can INNER JOIN the two tables via TestId and then GROUP BY the EngagementId so you get the sum of each engagement.
Something like this:
SELECT
ET.EngagementId,
SUM(T.TestCost)
FROM
EngagementTest ET
INNER JOIN Test T
ON T.TestId = ET.TestId
GROUP BY
ET.EngagementId
It can be achieved using below query.
SELECT i.EngagementId, SUM(TestCost)
FROM EngagementTest i
INNER JOIN Test t
ON e.TestId = t.TestId
GROUP BY i.EngagementId

SQL - Loop through a list and add to a variable using sql select statements

I have data loaded in a table called Trades. Now I need to query this table, find elements that satisfy a particular condition and produce the trade value amount.
Here is the requirement
TradeAmt = 0
Loop for all Trades
{IF TradeId is 35
If type = 'I'
ADD (TradeAmt =TradeAmt + col_TradeAmt )
else
ADD (TradeAmt = TradeAmt + col_TradeAmtOverlap )
END-IF}
Return TradeAmt
Data:
Row1: tradeid=35, type=I, col_TradeAmt=10, col_TradeAmtOverlap=20
Row2: tradeid=35, type=S, col_TradeAmt=30, col_TradeAmtOverlap=40
Output: TradeAmt=50
How can i write this using SQL statements.
Well, in SQL you don't really loop over a sequence.
You write a statement that describes what you want to get from the set of data (e.g. the Trades table).
In your case, you want to accumulate all the elements in some way and provide that accumulation as a result, you can do that by using an aggregate function like SUM.
Something along these lines probably could work. Note that I'm nesting two queries here, the inner one to decide which column to treat as the "Amount" to accumulate depending on the Type of the trade and also to filter only the trade with Id 35, and the outer query performs the sum aggregate of all amounts:
SELECT SUM("Amount") FROM
(SELECT
CASE
WHEN Type = 'I' THEN col_TradeAmt
ELSE col_TradeAmtOverlap
END "Amount"
FROM Trades
WHERE TradeId = 35) "TradeAmt";

MS Access - Summing up a field to be used in another query is "duplicating" data

I am trying to sum up one field and use it in another query, but when I use the Totals button and then call that sum from the other query it considers that field as multiple instances but with the sum value in each one. How can I sum two fields in two different queries and then use those sums in another query? Note - I only separated them into 3 queries because I felt it would help me avoid "is not part of an aggregate function" errors.
Example Data
Inventory Query: This query groups by item and sums the qty_on_hand field
Item SumOfqty_on_hand
A 300
Job Material query: This query groups on the job's materials and sums up the qty_req field (quantity required to complete the job)
Item SumOfqty_req
A 500
When I make a third query to do the calculation [SumOfqty_req]-[SumOfqty_on_hand] the query does the calculation but for each record in the Job Material query.
Job Material Query
SELECT dbo_jobmatl.item,
IIf(([qty_released]-[qty_complete])<0,0,([qty_released]-[qty_complete]))*[matl_qty] AS qty_req
FROM new_BENInventory
INNER JOIN (dbo_jobmatl
INNER JOIN new_BENJobs
ON (new_BENJobs.suffix = dbo_jobmatl.suffix)
AND (dbo_jobmatl.job = new_BENJobs.job)
) ON new_BENInventory.item = dbo_jobmatl.item
GROUP BY dbo_jobmatl.item,
IIf(([qty_released]-[qty_complete])<0,0,([qty_released]-[qty_complete]))*[matl_qty];
Inventory Query
SELECT dbo_ISW_LPItem.item,
Sum(dbo_ISW_LPItem.qty_on_hand) AS SumOfqty_on_hand,
dbo_ISW_LP.whse,
dbo_ISW_LPItem.hold_flag
FROM (dbo_ISW_LP INNER JOIN dbo_ISW_LPItem
ON dbo_ISW_LP.lp_num = dbo_ISW_LPItem.lp_num)
INNER JOIN dbo_ISW_LPLot
ON (dbo_ISW_LPItem.lp_num = dbo_ISW_LPLot.lp_num)
AND (dbo_ISW_LPItem.item = dbo_ISW_LPLot.item)
AND (dbo_ISW_LPItem.qty_on_hand = dbo_ISW_LPLot.qty_on_hand)
GROUP BY dbo_ISW_LPItem.item,
dbo_ISW_LP.whse,
dbo_ISW_LPItem.hold_flag
HAVING (((Sum(dbo_ISW_LPItem.qty_on_hand))>0)
AND ((dbo_ISW_LP.whse) Like "BEN")
AND ((dbo_ISW_LPItem.hold_flag) Like 0));
Third Query
SELECT new_BENJobItems.item,
[qty_req]-[SumOfqty_on_hand] AS [Transfer QTY]
FROM new_BENInventory
INNER JOIN new_BENJobItems
ON new_BENInventory.item = new_BENJobItems.item;
Please note that anything that starts with dbo_ is a prefix for a table that sources the original data.
If any more clarification is needed I would be more than happy to provide it.
Looks like you need a GROUP BY new_BENJobItems.item on your final query along with a SUM() on the quantity. Or to remove the IIf(([qty_released]-[qty_complete])<0,0,([qty_released]-[qty_complete]))*[matl_qty] from your Job Material query. Or both. As written, the Job Material Query is going to return a record for every different key value in the joined input tables that has a distinct quantity, which doesn't seem like the granularity you want for that.