How to multiply all values in one column to make one number? - sql

In SQL Server, I am trying to multiply all values of a calculated column in a table in descending date order, to produce one number.
This is so I can calculate a factor that can be applied to a different table / value, i.e. multiplying every value in the "price rate" column to produce a "price factor"
So far I have been trying to use exp AND log functions with no luck.

There’s no PRODUCT() or MULTIPLY() aggregate function in SQL because it’s so likely to overflow. However, as you were trying to do, this can be done with LOG and EXP,
SELECT EXP(SUM(LOG(price_rate))) as price_factor
FROM yourTable
Note that using LOG/EXP like this with integer values will not usually produce exact integer results.

In absence of an aggregate "product" function in SQL, one method uses arithmetic: you can sum the logarithm of each value, then take the the exponential of the result.
select exp(sum(ln(price_rate))) as price_factor
from mytable
FOr this to work properly, all values of price_rate must be greater than 0.

Related

DATEIME_DIFF throwing error when using safe divide

I've created a query that I'm hoping to use to fill a table with daily budgets at the end of every day. To do this, I just need some simple maths:
monthly budget / number of days left in the month.
Then, at the end of the month, I can SUM all of the rows to calculate an accurate budget.
The query is as follows:
SELECT *,
ROUND(SAFE_DIVIDE(budget, DATETIME_DIFF(CURRENT_DATE(), LAST_DAY(CURRENT_DATE()), DAY)),2) AS daily_budget
FROM `mm-demo-project.marketing_hub.budget_manager`
When executing the query, my results present as negative numbers, which according to the documentation for this function, is likely caused by the result overflowing the result type.
View the results of the query.
I've made a fools guess at rounding the calculation. Needless to say that it did not work at all.
How can I stop my query from returning negative number?
use below
SELECT *,
ROUND(SAFE_DIVIDE(budget, DATETIME_DIFF(LAST_DAY(CURRENT_DATE()), CURRENT_DATE(), DAY)),2) AS daily_budget
FROM `mm-demo-project.marketing_hub.budget_manager`

How to calculate the avg time a tool stays on hold? oracle sql developer

Im trying to calculate the average time a tool stays on loan. The time a tool stays on loan is the number of days between loan_status_change_date and tool_out_date (table columns). the date type of these 2 columns is ex: 01-SEP-17
whats the best way to approach this?
We can do arithmetic with Oracle dates. It's not clear from the column names which one is the start of the loan and which the end; in the following example I've assumed loan_status_change is when the tool is returned.
select tool
, avg(loan_status_change - tool_out_date) as avg_loan_days
from your_table
group by tool
/
The AVG() function is an aggregate function, so it handles the /ns for us. The substraction is to calculate the length of a particular loan, which is the value you want to average. The result of that substraction already is a number of days, so no further transformation is necessary. If your columns have a time element then the result might not be an integer.

SQL Server : aggregate function doesn't work?

I have imported a price list from a csv to my SQL Server database. That has worked fine. But now some weird stuff. Table is named PRICE which includes a column (and some more) Endprice and a total of 761 rows. All datatypes are varchar(50).
SELECT MAX(Endprice)
FROM PRICE
When I want this simple SQL statement to show the highest price in the column, I get a wrong result. I don't know why.
I get 98,39 as a result, but that's definitively wrong, it must be 100,73.
Here you can see a part of the data:
And now the wrong MAX() result:
BUT when I'm using the MIN function I get the highest one!? The min is somewhere at ~50 (not shown in the screenshot part).
`
The resultset of SELECT Endprice FROM PRICE is correct. I am at my wit's end.
This is because your column is a varchar, so it is determining the min or max based on characters. The column should be a decimal or money type, so it sorts by the value of your number (instead of an alphabetic sort like you are getting now).
Alphabetic sort: 9 is more than 1, thus 98.39 is the max.
The reason is because price is a varchar().
Here are two solutions:
order by len(price), price
This works assuming that all the price values have the same structure.
Or:
order by cast(price as float)
If you could have non-numeric values (always a danger when storing numbers in the wrong data type):
order by (case when isnumeric(price) = 1 then cast(price as float) end)
Or better yet:
alter table alter column price money
Then you don't have to worry about having the wrong type for the column.
Your problem is Endprice columns is varchar(50), therefore it is comparing strings not numbers, which means that a 9>1 no matter what cames next of the first digit. You have to convert it to a number before the max!
Also you really should consider in doing what #a_horse_with_no_name suggested change your column into a number like column type.
This is a example on how you solve your actual problem
select max(cast(endprice as money)) from sample
See it here: http://sqlfiddle.com/#!3/767f6/1
Note that I used . as a decimal separator it will depend on your database language setup.

Greatest date from list of date

I have this simple data base:
7/2/2013
7/13/2013
I write a simple SQL statement to select the greatest date from a list of date. I try to use the (max function) as follow:
select max([P_Date]) from [BalDB].[dbo].[tab_Product]
The result was incorrect; it gives me the smallest date not the greatest as follow:
7/2/2013
So please help me to know what is the problem in my SQL statement and how can I solve it
Problem: Get the greatest date from a list of date or compare it with local date and take the greater!!
The sql max function returns the largest value of the selected column, in your case since your data type is a nvarchar the largest value is what is alphabetically larger, which in this case is 7/2/2013 (since the "2" is greater then the "1" in "13").
What you need to do is basically what #David mentioned, either chance the data type of the column or if it isn't feasible then you can cast it in your query as a datetime
For example
select max(cast([P_Date] as datetime)) from [BalDB].[dbo].[tab_Product]
The max function is making this slower than it needs to be, try this.
select top 1 convert(datetime,P_Date) from [BalDB].[dbo].[tab_Product] order by convert(datetime,P_Date) desc
Now your dates should be date types, not varchars, but for the sake of querying your data as is, this will work.

using SUM and presenting result as absolute (ABS)

I have both positive and negative numbers (money) in a column and need to:
SUM the total ie. SUM(myColumn) based on if the numbers are +/-
Present the result as an absolute ie. even though the result is -1234 it should be presented as 1234
SQL is not my trade as you probably notice but we've solved most other issues but this one so any help is appriciated. Keep in mind my skill level is very low
You will have to use a combination of the sum and abs aggregate functions in SQL. Since you want the absolute value of the sum, the sum function will need to be called inside the call to abs:
select abs(sum(columnName)) from table
That should work for both SQL Server, MySQL, and Oracle.
Try one (or more) of these
SELECT SUM(moneyColumn) FROM MyTable
SELECT SUM(ABS(moneyColumn) FROM MyTable
SELECT ABS(SUM(moneyColumn) FROM MyTable