how to increase the max value keeping string lenght - sql

I have a column numbers from 1 to 10000, they are stored like string with 8 characters, so number 1 is stored like 00000001 and 10000 is stored like 00010000.
I need to take the max for this column and increase by 1 in insert operations. but if I do:
Max(column)+1
I lost previous 0, so I have 10001 and not 00010001, how I can keep zeros?

You can use the FORMAT function to format numbers:
SELECT FORMAT(1, '00000000') -- 00000001
Having said that, you should be storing numbers inside the database as-is and format them in the application.

you could try using cast and replicate
replicate('0', 8 - CONVERT(varchar(8), max(CAST(column AS INT)) +1) ) + CONVERT(varchar(8), max(CAST(column AS INT)) +1)
anyway you should take a look for identity in sqlserver for manage autoincrement column automatically

Related

SQL Convert & Cast Nvarchar Time to a decimal

I'm working on a legacy database and need to parse info from one database to another, parsing it into the new database is easy enough but first I need to create the query to convert and cast the following in the legacy SQL Server database:
WorkedHours(NVARCHAR(10)) is in text format 07:30
I need to convert and cast this as a decimal ie 7.5
I have searched around for the answer to this but can not find anything that has worked, so thought I would put it out there to see if any of you has any ideas.
Edit - What I should of asked is. What is causing an error converting to an int from a character with a value of 0 when trying to trying to convert and cast a time to a decimal?
DATEDIFF(
MINUTE,
0,
CAST('07:30' AS TIME)
)
/
60.0
Works up to '23:59' only
EDIT:
Based on a comment elsewhere, you have some 'bad' values.
This may find them...
SELECT
*
FROM
yourTable
WHERE
TRY_CONVERT(TIME, worked_hours) IS NULL
And as such, this is a safer version of my expression....
DATEDIFF(
MINUTE,
0,
TRY_CONVERT(TIME, worked_hours)
)
/
60.0
(Returns NULL for values that failed to parse.)
There's no reason to pull out the date/time types. Just do some simple string parsing:
cast(left(right('0' + WorkedHours, 5), 2) as int)
+ cast(right(WorkedHours, 2) as int) / 60.00
This won't have any limitations on 24 hours or anything like that. It just assumes that you've got one or two digits before a colon and two digits after.
This should work in SQL Server and an example-string "1101:56" (1101h & 56 minutes) | in general from 0h to >24h:
-- Take all hours before ":" and all Minutes (2 digits) after ":" and convert it to decimal.
select convert(decimal,left('1101:56',CHARINDEX(':','1101:56')-1)) + ( convert(decimal,right('1101:56',2))/60 );
-- with column-placeholder "time_str_from_table"
select convert(decimal,left(time_str_from_table,CHARINDEX(':',time_str_from_table)-1)) + ( convert(decimal,right(time_str_from_table,2))/60 );
If the source table have NULL-Values, than use "ISNULL" with substitution-value "0.0":
-- with column-placeholder "time_str_from_table"
select isnull( ( convert(decimal,left(time_str_from_table,CHARINDEX(':',time_str_from_table)-1)) + ( convert(decimal,right(time_str_from_table,2))/60) ), 0.0);

Convert date to number data type

I am trying to convert date to number like below, not sure which function works better.
Database used is SQL Server.
Table details
create table test
(
id varchar(255),
call_date varchar(255)
);
insert into test('26203', '14-Aug-2020');
I need output as 4405726203 -- its concatenation of date (14-Aug-2014) + id (26203)
This is too long for a comment.
SQL Server allows you to convert a datetime to a float. That would be:
select cast(dte as float)
from (values (convert(datetime, '14-Aug-2020'))) v(dte)
However, the corresponding floating point value is 44055 (https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d142a64db0872e7572eb4fbd6d5d5fe7). It is a bit of mystery what your intention is.
You could subtract 2, but that seems arbitrary. You could calculate the number of days since 1899-12-30. But that also seems arbitrary.
In any case, once you figure out how to convert the date to the number you want, just use concat() to combine the values.
I have found the solution:
convert(varchar,CAST(CONVERT(datetime,call_date) as bigint)) + id
Under the hood, a SQL Server DateTime is a tuple of 2 32-bit integers:
The first integer is a count of days since since the epoch, which for SQL Server is 1 January 1900
The second integer is a count of milliseconds since start of day (00:00:00.000). Except that the count ticks up in 3- or 4-milliscond increments. Microsoft only knows why that decision was made.
You can get the count of days since the epoch with
convert( int, convert( date, t.call_date ) )
[wrap that in convert(varchar, ... ) to turn it into a string]
Looks like your id is already a varchar, so you can say:
select compound_key = convert(varchar,
convert(int,
convert(date,
call_date
)
)
)
+ t.id
from test t
I would suggest padding both fields with leading zeros to a fixed length so as to avoid possible collisions (assuming you're trying to generate a key here). Signed 32-bit integer overflows a 2.1 billion-ish, so 9 digits for each field is sufficient.
This works
select concat(datediff(d, 0, cast(call_date as date)), id)
from
(values ('26203','14-Aug-2020')) v(id, call_date);
Results
4405526203

SQL date format from float (without a '1')

I have been given some data where there is a 'float' column that contains a date with a 1 in the front of it. I.e the value 1171030 represents 30th October 2017.
I am stuck in attempting to convert it to a normal date, when attempting to remove the one a dot appears (i.e. .171030).
Would really appreciate some guidance.
Many thanks
Yuck! Let's try datefromparts():
select datefromparts((val - 100000) / 10000, floor(val / 100) % 100, val % 100)
Or, here is another approach:
select convert(date, right(convert(varchar(255), cast(val as int)), 6))
SQL Server is actually pretty flexible in the date formats it understands.
I'm assuming this was probably produced by a non-Y2K compliant method such as JavaScript getYear() which simply returns current year minus 1900. It's not clear to me whether this data is coming from a flat file or it is already imported into a database table.
If you treat this value as a character string:
case length(val)
when 7 then cast('20' + right(val, 6) as date)
when 6 then cast('19' + val as date)
end
If you truly have a float (or int) value:
cast(cast(cast(19000000 + #val as int) as char(8)) as date)
In this case you'll need to convert through a character value rather than going straight to date. Be careful with string conversions from float to char. If you prefer shorter then you may be able to get away with this one:
cast(str(19000000 + #val, 8) as date);
You might get errors by assuming a length of 8 but that's probably a good way to catch and prevent problems.

How can convert 15000000.00 to 15,000,000 in SQL server?

There is a one value 15000000.00 with Numeric datatype in SQL server.
How can i get or convert the value 15000000.00 to 15,000,000?
The database server is the wrong place to do this. Localization should be handled in the presentation layer, not the datastore.
Since you're working with the money type, or you want the result to be a money type it could be as simple as:
SELECT CONVERT(VARCHAR, #money_val, 1) -- you may have to cast to money from int first
Check out this link for a deeper discussion:
Here is an excerpt:
Comma-formatting is available only for
MONEY data types. If you want to
comma-format INT, DECIMAL etc, you
should cast it to MONEY and do a
convert with style flag 1.
DECLARE #m DECIMAL(10,2) SELECT #m =
'23456789.25'
SELECT
CONVERT(VARCHAR, #m, 1) AS DecimalValue,
CONVERT(VARCHAR, CAST(#m AS MONEY), 1) AS MoneyValue /*
DecimalValue
MoneyValue
23456789.25 23,456,789.25
*/
This is not a conversion. 15.000.000,00 (german writing) is the string representation of 15 million. A decimal data type does not store the string, but the value.
All string represenration you see are basically visualizations - in enterprise manager or software according to the settings (locale) when generating the string.
I've always used the following with success
SELECT
Convert(VARCHAR, Cast(100000.01 AS MONEY), 1) Amount
Results:
Amount
-----------------------------
100,000.01
You don't want to save your numeric data in formats. You can do this when selecting:
SELECT CONVERT(varchar(12), value, 1) AS formattedvalue FROM table
The last 1 is a convert style that puts in the . and , signs (depending on your local settings and numeric type).
If you ask me, I wouldn't even let the SQL database server worry about this and format the number in code itself.

SQL Server 2008: Varchar Conversion to Numeric Data Overflow, Probably Because Some Are Ranges

I'm working on a query with a varchar column called ALCOHOL_OZ_PER_WK. Part of the query includes:
where e.ALCOHOL_OZ_PER_WK >= 14
and get the errors:
Arithmetic overflow error converting varchar to data type numeric.
and:
Error converting data type varchar to numeric.
Looking into the values actually stored in the column, the largest look close to 100, but some of the entries are ranges:
9 - 12
1.5 - 2.5
I'd like to get the upper limit (or maybe the midpoint of the range) from rows with entries like this and have it be the value being compared to 14.
What would be the (or an) easy way to do this?
As always, thank you!
Your DB is obviously result of some survey, and it seems to contain the original survey data. The usual way is to run this through an ECCD (Extract, Clean, Conform, Deliver) process and store clean and standardized data into a separate database (maybe a warehouse) which can then be used for analytics and reporting.
If you have SSIS use data profiling task to get an idea of types of strings you have in there. The Column Pattern Profile reports a set of regular expressions on the string column, so you will get an idea of what's inside those strings. If you do not have SSIS, you can use eobjects DataCleaner to do the same.
If you can not spare a new database or at least a new table -- at minimum add a numeric column to this table and then extract numeric values form those strings into the new column. You may want to use "something else" (SSIS, Pentaho Kettle, Python, VB, C#) to do this -- in general T-SQL in not very good at string processing.
My guess is that this is not the only column that has garbage inside, so any analysis that you may run on this may be worthless.
And if you still think that the ranges are the only problem, this example may help:
First some data
DECLARE #myTable TABLE (
AlUnits varchar(10)
) ;
INSERT INTO #myTable
(AlUnits )
VALUES ( '10' )
, ( '15' )
, ( '20' )
, ( '7 - 12' )
, ( '3 - 5' )
;
The query splits records into two groups, numeric and not numeric -- assumed ranges.
;
WITH is_num
AS ( SELECT CAST(AlUnits AS decimal(6, 2)) AS Units_LO
,CAST(AlUnits AS decimal(6, 2)) AS Units_HI
FROM #myTable
WHERE ISNUMERIC(AlUnits) = 1
),
is_not_num
AS ( SELECT CAST( RTRIM(LTRIM(LEFT(AlUnits,
CHARINDEX('-', AlUnits) - 1)))
AS decimal(6,2)) AS Units_LO
,CAST(RTRIM(LTRIM(RIGHT(AlUnits,
LEN(AlUnits)
- CHARINDEX('-', AlUnits))))
AS decimal(6,2)) AS Units_HI
FROM #myTable
WHERE ISNUMERIC(AlUnits) = 0
)
SELECT Units_LO
,Units_HI
,CAST(( Units_LO + Units_HI ) / 2.0 AS decimal(6, 2)) AS Units_Avg
FROM is_num
UNION ALL
SELECT Units_LO
,Units_HI
,CAST(( Units_LO + Units_HI ) / 2.0 AS decimal(6, 2)) AS Units_Avg
FROM is_not_num ;
Returns:
Units_LO Units_HI Units_Avg
----------- ----------- ----------
10.00 10.00 10.00
15.00 15.00 15.00
20.00 20.00 20.00
7.00 12.00 9.50
3.00 5.00 4.00
Not sure about easy ways.
A proper way is to store the numbers in two columns, ALCOHOL_OZ_PER_WK_MIN and ALCOHOL_OZ_PER_WK_MAX.
As you say you need to calculate numeric values, which you can then use in your query.
Probably the easiest way is to use some simple logic to calculate the average or upper limit using string functions, and string to numeric functions.
If all you want is the upper limit, just get the characters after the '-' and use that.
"probably because some are ranges" - do you get that "range" is not a SQL Server Data type? You've got non-numeric data you're trying to convert into numeric data, and you've got a scalar value you're comparing to a non-scalar value.
This database has some issues.