MS Access 2010 SQL query is rounding automatically to whole numbers - sql

All,
I'm running the SQL query below in MS Access 2010. Everything works fine except that the "a.trans_amt" column is rounded to a whole number (i.e. the query returns 12.00 instead of 12.15 or 96.00 instead of 96.30). Any ideas? I'd like it to display 2 decimal points. I tried using the ROUND function but didn't have any success.
Thanks!
INSERT INTO [2-Matched Activity] ( dbs_eff_date, batch_id_r1, jrnl_name,
ledger, entity_id_s1, account_s2, intercompany_s6, trans_amt,
dbs_description, icb_name, fdt_key, combo )
SELECT a.dbs_eff_date,
a.batch_id_r1,
a.jrnl_name,
a.ledger,
a.entity_id_s1,
a.account_s2,
a.intercompany_s6,
a.trans_amt,
a.dbs_description,
a.icb_name,
a.fdt_key,
a.combo
FROM [1-ICB Daily Activity] AS a
INNER JOIN
(
SELECT
b.dbs_eff_date,
b.batch_id_r1,
b.jrnl_name,
sum(b.trans_amt) AS ["trans_amt"],
b.icb_name
FROM [1-ICB Daily Activity] AS b
GROUP BY dbs_eff_date, batch_id_r1, jrnl_name, icb_name
HAVING sum(trans_amt) = 0
) AS b
ON (a.dbs_eff_date = b.dbs_eff_date) AND (a.batch_id_r1 = b.batch_id_r1) AND
(a.jrnl_name = b.jrnl_name) AND (a.icb_name = b.icb_name);

Essentially, you are attempting to append decimal precise values to an integer column. While MS Access does not raise a type exception it will implicitly reduce precision to fit the destination storage. To avoid these undesired results, set the precision type ahead of time.
According to MSDN docs, the MS Access database engine maintains the following numeric types:
REAL 4 bytes A single-precision floating-point value with a range of ...
FLOAT 8 bytes A double-precision floating-point value with a range of ...
SMALLINT 2 bytes A short integer between – 32,768 and 32,767.
INTEGER 4 bytes A long integer between – 2,147,483,648 and 2,147,483,647.
DECIMAL 17 bytes An exact numeric data type that holds values ...
And the MS Access GUI translates these as Field Sizes in table design interface where the default format of Number is Long Integer type.
Byte — For integers that range from 0 to 255. Storage requirement is a single byte.
Integer — For integers that range from -32,768 to +32,767. Storage requirement is two bytes.
Long Integer — For integers that range from -2,147,483,648 to +2,147,483,647 ...
Single — For numeric floating point values that range from -3.4 x 1038 to ...
Double — For numeric floating point values that range from -1.797 x 10308 to ...
Replication ID — For storing a GUID that is required for replication...
Decimal — For numeric values that range from -9.999... x 1027 to +9.999...
Therefore, in designing your database, schema, and tables, select the appropriate values to accommodate your needed precision. If not using the MS Access GUI program, you can define type in a DDL command:
CREATE TABLE [2-Matched Activity] (
...
trans_amt DOUBLE,
...
)
If table already exists consider altering design with another DDL command.
ALTER TABLE [2-Matched Activity] ALTER COLUMN trans_amt DOUBLE
Do note: if you run CREATE and ALTER commands in Query Design window, no prompts or confirmation will occur but changes will render.

Related

FormatNumber replacing number with 0

Not understanding this:
Number returned from DataReader: 185549633.66000035
We have a requirement to maintain the number of decimal places per a User Choice.
For example: maintain 7 places.
We are using:
FormatNumber(dr.Item("Field"), 7, TriState.false, , TriState.True)
The result is: 185,549,633.6600000.
We would like to maintain the 3 (or 35) at the end.
When subtracting two numbers from the resulting query we are getting a delta but trying to show these two numbers out to 6,7,8 digits is not working thus indicating a false delta to the user.
Any advice would be appreciated.
Based on my testing, you must be working with Double values rather than Decimal. Not surprisingly, the solution to your problem can be found in the documentation.
For a start, you should not be using FormatNumber. We're not in VB6 anymore ToTo. To format a number in VB.NET, call ToString on that number. I tested this:
Dim dbl = 185549633.66000035R
Dim dec = 185549633.66000035D
Dim dblString = dbl.ToString("n7")
Dim decString = dec.ToString("n7")
Console.WriteLine(dblString)
Console.WriteLine(decString)
and I saw the behaviour you describe, i.e. the output was:
185,549,633.6600000
185,549,633.6600004
I read the documentation for the Double.ToString method (note that FormatNumber would be calling ToString internally) and this is what it says:
By default, the return value only contains 15 digits of precision although a maximum of 17 digits is maintained internally. If the value of this instance has greater than 15 digits, ToString returns PositiveInfinitySymbol or NegativeInfinitySymbol instead of the expected number. If you require more precision, specify format with the "G17" format specification, which always returns 17 digits of precision, or "R", which returns 15 digits if the number can be represented with that precision or 17 digits if the number can only be represented with maximum precision.
I then tested this:
Dim dbl = 185549633.66000035R
Dim dblString16 = dbl.ToString("G16")
Dim dblString17 = dbl.ToString("G17")
Console.WriteLine(dblString16)
Console.WriteLine(dblString17)
and the result was:
185549633.6600004
185549633.66000035

Datatype conversion error in pentaho

Hi I have a table column named "sku" which of type integer and another column "total_sku" which again is of type integer , when I'm trying to calculate the percentage(100 * sku/total_sku) using Calculator step. I'm expecting an integer but its giving me 0.00 , kindly help
Thanks in advance.
sku total_sku percentage
23 2115 1.087
40 2115 1.891
My guess is that the calculator is doing the division before the multiplication, computing 100*(A/B), rather than (100*A)/B. Since you are dealing with integers, it is rounding A/B down to zero, and that is the end of it for you.
The calculator step lets you break a calculation down into multiple smaller components, all within the step. You can even specify which fields created in those substeps should stay in the stream, and which should are temporary values that should be discarded.
So try first doing a calculation such as tempValue = 100*A, then result = tempValue/B. Set Value type to Integer in both steps.
In the Calculator step, put 'Value type' as 'Integer'

Number format type REAL

I have a question about the format of numbers REAL.
I have a column with this type and after I insert 8 numbers for this column, it doesn't let me to save.
Example: 11406760
When I try with a 7 digit numbers like 1140676, it lets me to save the data.
Any idea why this happens?
If I read this MSDN page correctly, REAL is a synonym for FLOAT(24), which has a precision of 7 digits.
This means that while a column of this type does support values up to about 10^38, it only keeps about 7 most significant digits of that value. So for an 8 digit number, the final digit may not be stored correctly.
Do you really need a REAL (=floating point) value for this column (maybe check out decimal), or rather some integer type?

Why & When should I use SPARSE COLUMN? (SQL SERVER 2008)

After going thru some tutorials on SQL Server 2008's new feature "SPARSE COLUMN", I have found that it doesn't take any space if the column value is 0 or NULL but when there is a value, it takes 4 times the space a regular(non sparse) column holds.
If my understanding is correct, then why I will go for that at the time of database design?
And if I use that, then at what situation will I be?
Also out of curiosity, how does no space get reserved when a column is defined as sparse column (I mean to say, what is the internal implementation for that?)
A sparse column doesn't use 4x the amount of space to store a value, it uses a (fixed) 4 extra bytes per non-null value. (As you've already stated, a NULL takes 0 space.)
So a non-null value stored in a bit column would be 1 bit + 4 bytes = 4.125 bytes. But if 99% of these are NULL, it is still a net savings.
A non-null value stored in a GUID (UniqueIdentifier) column is 16 bytes + 4 bytes = 20 bytes. So if only 50% of these are NULL, that's still a net savings.
So the "expected savings" depends strongly on what kind of column we're talking about, and your estimate of what ratio will be null vs non-null. Variable width columns (varchars) are probably a little more difficult to predict accurately.
This Books Online Page has a table showing what percentage of different data types would need to be null for you to end up with a benefit.
So when should you use a Sparse Column? When you expect a significant percentage of the rows to have a NULL value. Some examples that come to mind:
A "Order Return Date" column in an order table. You would hope that a very small percent of sales would result in returned products.
A "4th Address" line in an Address table. Most mailing addresses, even if you need a Department name and a "Care Of" probably don't need 4 separate lines.
A "Suffix" column in a customer table. A fairly low percent of people have a "Jr." or "III" or "Esquire" after their name.
Storing a null in a sparse column takes up no space at all.
To any external application the column will behave the same
Sparse columns work really well with filtered indexes as you will only want to create an index to deal with the non-empty attributes in the column.
You can create a column set over the sparse columns that returns an xml clip of all of the non-null data from columns covered by the set. The column set behaves like a column itself. Note: you can only have one column set per table.
Change Data Capture and Transactional replication both work, but not the column sets feature.
Downsides
If a sparse column has data in it it will take 4 more bytes than a normal column e.g. even a bit (0.125 bytes normally) is 4.125 bytes and unique identifier rises form 16 bytes to 20 bytes.
Not all data type can be sparse: text, ntext, image, timestamp, user-defined data type, geometry, or geography or varbinray (max) with the FILESTREAM attribute cannot be sparse. (Changed17/5/2009 thanks Alex for spotting the typo)
computed columns can't be sparse (although sparse columns can take part in a calculation in another computed column)
You can't apply rules or have default values.
Sparse columns cannot form part of a clustered index. If you need to do that use a computed column based on the sparse column and create the clustered index on that (which sort of defeats the object).
Merge replication doesn't work.
Data compression doesn't work.
Access (read and write) to sparse columns is more expensive, but I haven't been able to find any exact figures on this.
Reference
You're reading it wrong - it never takes 4x the space.
Specifically, it says 4* (4 bytes, see footnote), not 4x (multiply by 4). The only case where it's exactly 4x the space is a char(4), which would see savings if the NULLs exist more than 64% of the time.
"*The length is equal to the average of the data that is contained in the type, plus 2 or 4 bytes."
| datetime NULL | datetime SPARSE NULL | datetime SPARSE NULL |
|--------------------|----------------------|----------------------|
| 20171213 (8 bytes) | 20171213 (12 bytes) | 20171213 (12 bytes) |
| NULL (8 bytes) | 20171213 (12 bytes) | 20171213 (12 bytes) |
| 20171213 (8 bytes) | NULL (0 bytes) | NULL (0 bytes) |
| NULL (8 bytes) | NULL (0 bytes) | NULL (0 bytes) |
You lose 4 bytes not just once per row; but for every cell in the row that is not null.
From SQL SERVER – 2008 – Introduction to SPARSE Columns – Part 2 by Pinal Dave:
All SPARSE columns are stored as one XML column in database. Let us
see some of the advantage and disadvantage of SPARSE column.
Advantages of SPARSE column are:
INSERT, UPDATE, and DELETE statements can reference the sparse columns by name. SPARSE column can work as one XML column as well.
SPARSE column can take advantage of filtered Indexes, where data are filled in the row.
SPARSE column saves lots of database space when there are zero or null values in database.
Disadvantages of SPARSE column are:
SPARSE column does not have IDENTITY or ROWGUIDCOL property.
SPARSE column can not be applied on text, ntext, image, timestamp, geometry, geography or user defined datatypes.
SPARSE column can not have default value or rule or computed column.
Clustered index or a unique primary key index can not be applied SPARSE column. SPARSE column can not be part of clustered index key.
Table containing SPARSE column can have maximum size of 8018 bytes instead of regular 8060 bytes. A table operation which involves SPARSE
column takes performance hit over regular column.

How to store decimal values in SQL Server?

I'm trying to figure out decimal data type of a column in the SQL Server. I need to be able to store values like 15.5, 26.9, 24.7, 9.8, etc
I assigned decimal(18, 0) to the column data type but this not allowing me to store these values.
What is the right way to do this?
DECIMAL(18,0) will allow 0 digits after the decimal point.
Use something like DECIMAL(18,4) instead that should do just fine!
That gives you a total of 18 digits, 4 of which after the decimal point (and 14 before the decimal point).
You should use is as follows:
DECIMAL(m,a)
m is the number of total digits your decimal can have.
a is the max number of digits you can have after the decimal point.
http://www.tsqltutorials.com/datatypes.php has descriptions for all the datatypes.
The settings for Decimal are its precision and scale or in normal language, how many digits can a number have and how many digits do you want to have to the right of the decimal point.
So if you put PI into a Decimal(18,0) it will be recorded as 3?
If you put PI into a Decimal(18,2) it will be recorded as 3.14?
If you put PI into Decimal(18,10) be recorded as 3.1415926535.
For most of the time, I use decimal(9,2) which takes the least storage (5 bytes) in sql decimal type.
Precision => Storage bytes
1 - 9 => 5
10-19 => 9
20-28 => 13
29-38 => 17
It can store from 0 up to 9 999 999.99 (7 digit infront + 2 digit behind decimal point = total 9 digit), which is big enough for most of the values.
You can try this
decimal(18,1)
The length of numbers should be totally 18. The length of numbers after the decimal point should be 1 only and not more than that.
In MySQL DB decimal(4,2) allows entering only a total of 4 digits. As you see in decimal(4,2), it means you can enter a total of 4 digits out of which two digits are meant for keeping after the decimal point.
So, if you enter 100.0 in MySQL database, it will show an error like "Out of Range Value for column".
So, you can enter in this range only: from 00.00 to 99.99.
The other answers are right. Assuming your examples reflect the full range of possibilities what you want is DECIMAL(3, 1). Or, DECIMAL(14, 1) will allow a total of 14 digits. It's your job to think about what's enough.
request.input("name", sql.Decimal, 155.33) // decimal(18, 0)
request.input("name", sql.Decimal(10), 155.33) // decimal(10, 0)
request.input("name", sql.Decimal(10, 2), 155.33) // decimal(10, 2)