PostgreSQL sum typecasting as a bigint - sql

I am doing the sum() of an integer column and I want to typecast the result to be a bigint - to avoid an error. However when I try to use sum(myvalue)::bigint it still gives me an out of range error.
Is there anything that I can do to the query to get this to work? Or do I have to change the column type to a bigint?

The current manual is more explicit than it used to be in 2013:
sum ( integer ) → bigint
If your column myvalue indeed has the type integer like you say, then the result is bigint anyway, and the added cast in sum(myvalue)::bigint is just noise.
Either way, to get an "out of range" error, the result would have to be bigger than what bigint can hold:
-9223372036854775808 to +9223372036854775807
One would have to aggregate a huge number of big integer values (>= 2^32 * 2^31). If so, cast the base column to bigint, thereby forcing the result to be numeric:
SELECT sum(myvalue::int8) ...
The more likely explanation is that your column has, in fact, a different data type, or the error originates from something else. Not enough detail in the question.

I solved my problem using following statement
SUM(CAST(gross_amount AS Integer))
This is give the result of the column as SUm bigint,
Note:My column gross_amount was double type.

You need to cast it before doing the operation:
SUM(myvalue::bigint)

Related

CASTING to NUMERIC in SQL

I am trying to understand the ARPU calculation in SQL from the following code, however I don't understand why the author has used NUMERIC with revenue in the 2nd query? Won't revenue (meal_price * order quantity) be numeric anyway?
The issue is probably the following. NUMERIC is a specific data type. However, it is not clear that meal_price and order_quantity are specifically NUMERIC -- and not some other type such as INT.
Many databases do integer division for INT, so 1 / 2 is 0 rather than 0.5.
The conversion to NUMERIC is a simple way to avoid integer division.
Of course if a and b are numeric types , a * b will be numeric type
But there are many different numeric types, see
https://www.postgresql.org/docs/13/datatype-numeric.html
NUMERIC is a KEYWORK to specify numeric type of arbitrary précision, see previous link, it's often used to do exact calculations (accouinting) that cannoy be done in foating type.
In your case the author choosed to define the type he wants to use and not let the system/db choose for him. (try to figure out if a and b are integer what shoult be the type of the result 2 * 4 / 3 ?). It's a good practice.

Search with inequalities on string property

We are using NHibernate over SQL Server and SQLite.
The database stores records in rows rather than columns -- each row having Path|Value as columns. Path and Value are both string properties.
For certain values of Path we would like to query for inequalities -- greater-than, less-than, etc.
The trouble we are having is that because the properties are strings, the inequalities are using string comparisons -- for example, searching for Value >= 18 returns rows where Value = 5. Unfortunately we are having trouble working around this.
1) This restriction produces incorrect results (saying 18 < 5):
Restrictions.Ge("Value", item.Value);
2) We tried casting the value to an integer, but this code produces a SqlException from NHibernate -- Error converting data type nvarchar to bigint.
Restrictions.Le(Projections.Cast(NHibernateUtil.Int64, Projections.Property("SearchString")), item.Value)
3) We were looking for a way to pad the property value with zeros (so that we would get 018 > 005), but could not find a way to do this in NHibernate.
Does anyone have any advice?
Thank you in advance!
Assuming that you want to compare on integer value, with IQueryOver:
1) This restriction produces incorrect results (saying 18 < 5):
Restrictions.Ge("Value", item.Value);
Restrictions.Ge
(
Projections.Cast(NHibernateUtil.Int32, Projections.Property<YourEntity>(x => x.YourProperty))
, intValue
)
Convert your datatype accordingly. If your C# datatype (intValue) is already numeric, no need to convert it. If your x.YourProperty is already numeric type, no need to convert it. Adjust above code accordingly.
2) We tried casting the value to an integer, but this code produces a SqlException from NHibernate -- Error converting data type nvarchar to bigint.
Restrictions.Le(Projections.Cast(NHibernateUtil.Int64, Projections.Property("SearchString")), item.Value)
Refer the above and check the datatype of item.Value.

How to avoid PG::NumericValueOutOfRange when using sum function

I have method like this:
def self.weighted_average(column)
sql = "SUM(#{column} * market_cap) / SUM(market_cap) as weighted_average"
Company.select(sql).to_a.first.weighted_average
end
When the column is a decimal, it returns a value without problem.
But when the column is integer, the method ends up with a PG::NumericValueOutOfRange error.
Should I change column type integer to decimal, or is there a way to get the result of sum without changing column type?
You can always make float from your integer.
def self.weighted_average(column)
column = column.to_f
sql = "SUM(#{column} * market_cap) / SUM(market_cap) as weighted_average"
Company.select(sql).to_a.first.weighted_average
end
You can cast your value to alway be a decimal value, thus no need to change the column type:
sql = "SUM(#{column} * CAST(market_cap as decimal(53,8))) / SUM(CAST(market_cap as decimal(53,8))) as weighted_average"
P.S. I would go with changing the column type - it is consistent then.
I would suggest you to change the datatype to decimal. Because, when SUM gets PG::NumericValueOutOfRange, it means that your datatype is not sufficient. It will lead to gracefully handle this scenario, instead of a workaround.
Postgres documentation says this about SUM() return type:
bigint for smallint or int arguments, numeric for bigint arguments,
otherwise the same as the argument data type
This means that you will somehow need to change datatype that you pass to SUM. It can be one of the following:
Alter table to change column datatype.
Cast column to other datatype in your method.
Create a view that casts all integer columns to numeric and use that in your method.
You are trying to place a decimal value into a integer parameter. Unless you use the ABS() value that will not be possible, unless you are 100% sure that the % value will always be 0.
Use type Float or function ABS() if you HAVE to have an INT
Yo could try casting column to decimal
sql = "SUM(CAST(#{column}) AS DECIMAL * market_cap) / SUM(market_cap) as weighted_average"

Returning a varchar value from a coalesced int calculation

I'm a newbie learning my way around T-SQL using the AdventureWorks2012 database. I'm using SQL Server 2014, though a solution that would also work with 2008 would be great. I've been given the below exercise:
Write a query using the Sales.SpecialOffer table. Display the difference between the MinQty and MaxQty columns along with the SpecialOfferID and Description columns.
Thing is, MaxQty allows for null values, so I'm trying to come up with a real world solution for an output that doesn't involve leaving nulls in there. However, when I try to use coalesce to return 'No Max' (yes, I get that I could just leave NULL in there but I'm trying to see if I can figure this out), I get the message that the varchar value 'No Max' couldn't be converted to data type int. I'm assuming this is because MaxQty - MinQty as an int takes precedence?
select
specialofferid
, description
, coalesce((maxqty - minqty),'No Max') 'Qty_Difference'
from
sales.specialoffer;
Error:
Msg 245, Level 16, State 1, Line 135
Conversion failed when converting the varchar value 'No max' to data type int.
I thought about just returning a nonsense integer (0 or a negative) but that doesn't seem perfect - if return 0 I'm obscuring situations where the result is actually zero, etc.
Thoughts?
You just need to make sure that all the parameters of the COALESCE function call have consistent data types. Because you can't get around the fact No Max is a string, then you have to make sure that the maxqty - minqty part is also treated as a string by casting the expression.
select specialofferid
, description
, coalesce(cast(maxqty - minqty as varchar),'No Max') 'Qty_Difference'
from sales.specialoffer;
EDIT: A few more details on the cause of the error
Without the explicit cast, the reason why the COALESCE function attempts to convert the No Max string to an int can be explained by the following documented rule:
Data type determination of the resulting expression is different. ISNULL uses the data type of the first parameter, COALESCE follows the CASE expression rules and returns the data type of value with the highest precedence.
And if you check the precedence of the different types, as documented here, then you will see that int has higher precedence than varchar.
So as soon as you have a mix of data types in the call to COALESCE, SQL Server will try to convert all mismatching parameters to the data type with highest precedence, in this case int. To override that default behavior, explicit type casting is required.
I would use a case statement to so you can do stuff you want.
select specialofferid
, description
, CASE
WHEN maxqty is null THEN 'No Max'
ELSE (maxqty - minqty) 'Qty_Difference'
END
from sales.specialoffer;

Multiplication with NULL and empty column values in SQL

This was my Interview Question
there are two columns called Length and Breadth in Area table
Length Breadth Length*Breadth
20 NULL ?
30 ?
21.2 1 ?
I tried running the same question on MYSQL while inserting,To insert an empty value I tried the below query . Am I missing anything while inserting empty values in MYSQL.
insert into test.new_table values (30,);
Answers: With Null,Result is Null.
With float and int multiplication result is float
As per your question the expected results would be as below.
SELECT LENGTH,BREADTH,LENGTH*BREADTH AS CALC_AREA FROM AREA;
LENGTH BREADTH CALC_AREA
20
30 0 0
21.2 1 21.2
For any(first) record in SQL SERVER if you do computation with NULL the answer would be NULL.
For any(second) record in SQL SERVER, if you do product computation between a non-empty value and an empty value the result would be zero as empty value is treated as zero.
For any(third) record in SQL SERVER, if you do computation between two non-empty data type values the answer would be a NON-EMPTY value.
Check SQL Fiddle for reference - http://sqlfiddle.com/#!3/f250a/1
That blank Breath (second row) cannot happen unless Breath is VARCHAR. Assuming that, the answers will be:
NULL (since NULL times anything is NULL)
Throws error (since an empty string is not a number. In Sql Server, the error is "Error converting data type varchar to numeric.")
21.20 (since in Sql Server, for example, conversion to a numeric type is automatic, so SELECT 21.2 * '1' returns 21.20).
Assuming that Length and Breadth are numerical types of some kind the second record does not contain possible values — Breadth must be either 0 or NULL.
In any event, any mathematical operation in SQL involving a NULL value will return the value NULL, indicating that the expression cannot be evaluated. The answer are NULL, impossible, and 21.2.
The product of any value and NULL is NULL. This is called "NULL propagation" if you want to Google it. To score points in an interview, you might want to mention that NULL isn't a value; it's a special marker.
The fact that the column Breadth has one entry "NULL" and one entry that's blank (on the second row) is misleading. A numeric column that doesn't have a value in a particular row means that row is NULL. So the second column should also show "NULL".
The answer to the third row, 21.2 * 1, depends on the data type of the column "Length*Breadth". If it's a data type like float, double, or numberic(16,2), the answer is 21.2. If it's an integer column (integer, long, etc.), the answer is 21.
A more snarky answer might be "There's no answer. The string "Length*Breadth" isn't a legal SQL column name."
In standard SQL they would all generate errors because you are comparing values (or nulls) of different types:
CAST ( 20 AS FLOAT ) * CAST ( NULL AS INTEGER ) -- mismatched types error
CAST ( '' AS INTEGER ) -- type conversion error
CAST ( AS INTEGER ) -- type conversion error
CAST ( 21.2 AS FLOAT ) * CAST ( 2 AS INTEGER ) -- mismatched types error
On the other hand, most SQL product would implicitly cast values when comparing values (or nulls) of different types according to type precedence e.g. comparing float value to an integer value would in effect cast the integer to float and result in a float. At the product level, the most interesting question is what happens when you compare a null of type integer with a value (or even a null) of type float...
...but, frankly, not terribly interesting. In an interview you are presented with a framework (in the form of questions asked of you) on which to present your knowledge, skills and experience. The 'answer' here is to discuss nulls (e.g. point out that nulls are tricky to define and behave in unintuitive ways, which leads to frequent bugs and a desire to avoid nulls entirely, etc) and whether implicit casting is a good thing.