Truncate (using ROUND) has stopped working after changing column data type - sql-server

I use the following query on the SQL Server 2008 database of a 3rd party product to generate some reports.
SELECT ROUND(SUM(Price),0,1) AS SumNetPrice FROM Transactions
Eg
SUM(Price): 1.2345678
ROUND(SUM(Price),0,1): 1
This has worked fine until now and removed all of the decimal places. In fact curiously the result was truncated even if I didn't specify the 3rd parameter as per the MSDN information http://msdn.microsoft.com/en-us/library/ms175003.aspx on the ROUND function.
The 3rd party company has now changed the data type of the Price column from 'real' to decimal(22, 7). Unfortunately this now means that I always get 7 decimal places even when I use the truncate option of the ROUND function. So now I get:
ROUND(SUM(Price),0,1): 1.0000000
Shouldn't the ROUND(expression,0,1) truncate the result so I don't get any decimal places? How can I remove these decimal places from the result in the SQL query?

In order to make it working the way it worked earlier is to Convert the type from decimal to real. Here is your updated query to get desired output.
select Cast(ROUND(SUM(Price),0,1) as Real) AS SumNetPrice FROM Transactions

SELECT CAST(ROUND(SUM(Price),0,1) AS DECIMAL(22,0)) AS SumNetPrice FROM Transactions

Related

DT_DBTIMESTAMP2 having only 3 digits

I'm having (DT_DBTIMESTAMP2,7)GETDATE() in SSIS Derived Column Transformation and Table column with datetime2(7).
Even though I set 7 Digit Second Scale in both, but seems it comes only 3 digit.
For example, I expected like '2018-05-02 16:45:15.6192346' but it comes '2018-05-02 16:45:15.6190000'.
The reason why I need the millseconds, I'd like to sort out the latest record from any duplications using timestamp. I realized only 3 digit second scale is not enough for this pourpose.
Except for Derived Column Transformation and Table Columns, is there any requrired setting in SSIS package? Any advices would be appreciated.
GETDATE() returns a datetime, you should use SYSDATETIME() instead. See documentation.
edit
As noted by Larnu, you are probably using SSIS expression GETDATE, rather that the sql expression GETDATE as I assumed. The point is more-or-less the same though. GETDATE returns a DT_DBTIMESTAMP, where "The fractional seconds have a maximum scale of 3 digits." (Source).
Although this is almost the same as what HoneyBadger has said, I'm expanding a little, as the OP isn't using the GETDATE() expression in SQL Server. The value 2018-05-02 16:45:15.619 could never be returned by GETDATE() (Transact-SQL) as it's only accurate to 1/300th of a second (thus the final digit can only every be 0,3, and 7 (technically 0, 333333333~ and 666666666~, which is why the final digit is a 7, as it's rounded up)).
In SSIS the GETDATE() expression returns a datatype of DB_TIMESTAMP. According to the Documentation:
A timestamp structure that consists of year, month, day, hour, minute,
second, and fractional seconds. The fractional seconds have a maximum
scale of 3 digits.
Thus, the last 4 characters are lost. Unfortunately, I don't believe there is a function in SSIS that returns the the current date and time to the accuracy you require. Thus, if you need this high level, you'll likely need to use an expression in SQL Server that does, such as SYSDATETIME() that HoneyBadger recommended.

Pervasive PSQL Control Centre / Currency data type

Having issues updating a Pervasive PSQL table using Pervasive Control Centre and wonder if anyone can point me in the right direction. I'm struggling to update a field in the table whose type is '254-VB Currency'.
Sample query:
Update TABLE set "remBal" = 100.00 where 'Posting' = 215288;
The value that ends up in the remBal field is 463673729135463.6288
Pervasive version is v10.30. Updating via e.g. VAccess control works fine. It's just Pervasive Control Centre that doesn't.
The VAccess control supports more data types than the standard PSQL engine does. The VB Currency data type is not one that's natively supported in PSQL.
According to MSDN, the Currency data type is defined as:
Currency variables are stored as 64-bit (8-byte) numbers in an integer
format, scaled by 10,000 to give a fixed-point number with 15 digits
to the left of the decimal point and 4 digits to the right. This
representation provides a range of -922,337,203,685,477.5808 to
922,337,203,685,477.5807.
What I would suggest, is enter 100.00 to the database using VAccess, then look at the value in Control Center. You can then use that value in your SQL statement. It's not pretty but it might work.

Does Nesbot Carbon error with trailing data and not with "too little" data?

I'm looking to confirm a theory of mine, but I really need to be sure first.
I have laravel 5.0 and SQL Server 2012.
when I have fields with the default datetime, I can't insert values with more than 3 microsecond spaces because the database errors out.
So if I set it to datetime2(3) I can insert a lot more microsecond spaces but only the first ones will be preserved that fit in the field.
If I set it the SQL Server grammar to 'Y-m-d H:i:s.u' it will try to insert a number with 6 spaces every time.
What i'm looking for is that carbon will not have issues with the fact that the database will return less than 6 numbers(namely the 3) and will continue to work properly in all cases without exceptions when I call a toArray() in laravel or something like that.
I can't do datetime2(7) because carbon then complains about trailing data.
So in short
Does carbon, with set dateformat Y-m-d H:i:s.u, gladly always accept a number with only 3 decimal place points, and happily insert a 6 decimal point into the database and not object that the database only saves up to 3 points?
For people looking into this issue:
I'm using datetime2(3) data fields in the database, and I use the Y-m-d H:i:s.u date notation without issue now for the last 2 months, even with all the wonky date stuff I sometimes throw at it, I've had no issues.
Only issues I had when I accidentally used datetime or datetime2(7)

Migration conversion of float data to decimal data

I am migrating data from one table to a new table. The old table uses FLOAT, and in the new table I am using DECIMAL as the field attribute.
I am using the following statement which worked fine:
CAST(OLD_COLUMN_NAME as DECIMAL(9,2) AS 'NEW_COLUMN_NAME'
that works like a charm until I hit the bump in the road. The old data is defined as float,null, the new field is defined as decimal(5,5). I understand that decimal(5,5) will requires all data behind the decimal for 5 positions. Just wondering if they is any way to handle this problem of moving data from a float data field to a decimal data field.
The input data from the old field is varied and looks like this: 5, 0.5, 0.5, 0.75, 2, and so forth.
The error I am receiving is:
Msg 8115, Level 16, State 6, Line 8 Arithmetic overflow error converting float to data type numeric.The statement has been terminated.
The code is against a SQL SERVER 2005 database using SQL SERVER 2008. Not sure this matters, but thought I would include this information.
Could someone shed some light on how to address this data conversion issue? Thank you!
Decimal(5, 5) only has a range - 0.99999 to + 0.99999
but you say you are trying to put 5 and 2 into it. Do you need Decimal(10, 5)?
If not you have indeed been left a bit of a conundrum.
I mention the following as a point of interest rather than a serious suggestion, though, who knows, it may be useful!
If the column is nullable one way to fullfill your bosses requirements would be
create table #t (j int,i Decimal(5, 5) null)
set ansi_warnings off
set arithabort off
insert into #t values(1,0.2345678)
insert into #t values(2,10)
insert into #t values(3,0.455464)
select * from #t
Output
Arithmetic overflow occurred.
j i
----------- ------------------------------
1 0.23457
2 NULL
3 0.45546
I would recommend doing something like this.
Cast(Round(field, 5) As Decimal(5, 5))
Does your boss understand that decimal(5,5) won't allow anything to the left of the decimal point?
Ask your boss what he/she wants in plain english. If your boss is really asking you to store numbers greater than .99999, but insisting specifically on "decimal(5,5)", then clearly they don't understand what they're asking for. The first "5" in decimal(5,5) refers to the total number of digits in the number (before and after combined)

display image on a report based on two date

I am using sql server 2005 reporting service to generate report base on a database. There are two columns which are datetime type ColumnA and ColumnB. The report would display a KPI image on this report by comparing these two columns.Below is the expression for selecting image
SWITCH(DateDiff("d",Fields!ColumnA.Value,Fields!ColumnB.Value)<0,"kpi_r",
DateDiff("d",Fields!ColumnA.Value,Fields!ColumnB.Value)>0,"kpi_g",
DateDiff("d",Fields!ColumnA.Value,Fields!ColumnB.Value)=0,"kpi_y")
For most of the records, the image is correct. Only for one record, the result is very strange.
For this record
ColumnA=2010-04-23 08:00:00 ColumnB=2010-04-22 17:00:00
It would display kpi_r, it displayed kpi_y. I have checked the value of DateDiff(d,Fields!ColumnA.Value,Fields!ColumnB.Value) in the SSMS, the value is -1. Why does it display kpi_y? Does anyone meet this problem before?
Best Regards,
The difference is that the SSMS DATEDIFF function counts the interval boundaries between the two dates whereas ReportBuilder counts the actual intervals. Within SSMS if you cross midnight you have triggered a day boundary so in your example you get -1. In ReportBuilder it is looking for 24 hours to be between the two values so you get 0. If you change the time on ColumnA to be '2010-04-23 17:00:00' you will see the value changes to -1 as you expected. For your comparison it would probably make sense to strip the time component from ColumnA and ColumnB when you do this SWITCH statement.
the above answer is spot on.
here's a few ways to strip time off a date depending on your preferences:
1. do it in RS: use and expression like dateserial(year(Fields!ColumnA.Value),month(Fields!ColumnA.Value), day(Fields!ColumnA.Value)) in your switch expression
2. do it in SQL: use an expression like cast(round(cast(ColumnA as float),0,1) as datetime) in your query

Resources