Represent a date with minimum possible character using SQL Query - sql

I'm trying to represent a Date in symbolic format, and the goal is to do it with minimum characters with only integer or English Alphabets
What I tried is below SQL Server Query:
SELECT format(CAST(DATEDIFF(day, CAST('1900-01-01' AS DATE), CAST('2100-01-01' AS DATE)) AS INT), '00000')
This query give result 73049, which is quite good to represent a date in 5 characters for as long as two centuries. With this I can very easily get the Date which it represent, making '1900-01-01' or some other date as fixed start date, as per my Application need.
I'm looking for possibility to reduce character length further.

Related

Fetching min of current date from a lot of date strings in a single column

In a specific column I have grouped all the dates with timestamp sorted ASC as a string with ; seperator and that column can contain 1 - 50 date strings. From the date strings I have, i need to fetch the latest dates Min value.
Sample, (let's assume sysdaye date is 07/25/2019).
07/24/2019 12:02:44;
07/24/2019 12:03:56;
07/24/2019 10:02:44;
07/25/2019 12:02:44;
07/25/2019 12:03:56.
I am not certain the date value I wanted comes in the certain position and I know it can be done with RegEx. Can someone give me a RegEx for this or a suitable suggestion to do this any other way in Oracle SQL?
Assuming all your dates are sorted and have exactly one format, here's regex solution
select
dates,
regexp_substr(
dates,
concat(
regexp_substr(regexp_substr(dates, '(\d|\s|/|:|-)+$'), '(\d|/|:|-)+'),
'(\d|\s|/|:|-)+')
) as max_date_min_datetime
from
<table_name>

How would SQL treat this date format?

I had a coworker run a data pull for me. The query was essentially
SELECT a, b, c
FROM table
WHERE date >= 06/01/2018
The where clause being June 1, 2018. The query ran but the date filter was incorrect (not ‘2018-06-01’) How did the server interpret the date used? Was any filtering applied?
If you specified exactly as you have shown it, without quotes, then it would probably have:
1) Calculated 6 divided by 1 divided by 2018 (resulting in an integer zero)
2) Converted the dates in your database to an int to match the compare data type, and done a compare.
I expect this returned all your rows.
You can use this (datediff) function.
SELECT a, b, c
FROM table
WHERE datediff(dateVar, from_unixtime(unix_timestamp('2018/06/01','yyyy/MM/dd'),'yyyy-MM-dd')) >= 0
from_unixtime(,'yyyy-MM-dd') converts string to a string of given format, e.g. '2018-06-01'
Alternatively, these are functions which can help:
date_sub(,xxx) subtracts xxx days from the string, and returns a new
string in the same format.
unix_timestamp(string date,string pattern) converts a
string of a given pattern to unix time stamp, ) if fail.
Reference: How to change date format in hive?
This condition is:
WHERE date >= 06/01/2018
The last part is a numerical expression which I believe is interpreted as (06 / 01) / 2018. Depending on the database, this would either be 0 or about 0.00297, depending on whether your database does integer division.
Now the database has a bit of a conundrum. It has a date on one side and a number on the other. The rules of type conversion say to convert the date to a number. Depending on the database, this could be an error or a valid number -- which would be larger than 0.
The correct way to express this is:
WHERE date >= '2018-06-01'
or:
WHERE date >= DATE '2018-06-01'

Date range comparison using varchar columns in Teradata

I've been tasked to take a calendar date range value from a form front-end and use it to, among other things, feed a query in a Teradata table that does not have a datetime column. Instead the date is aggregated from two varchar columns: one for year (CY = current year, LY = last year, LY-1, etc), and one for the date with format MonDD (like Jan13, Dec08, etc).
I'm using Coldfusion for the form and result page, so I have the ability to dynamically create the query, but I can't think of a good way to do it for all possible cases. Any ideas? Even year differences aside, I can't think of anything outside of a direct comparison on each day in the range with a potential ton of separate OR statements in the query. I'm light on SQL knowledge - maybe there's a better way to script it in the SQL itself using some sort of conversion on the two varchar columns to form an actual date range where date comparisons could then be made?
Here is some SQL that will take the VARCHAR date value and perform some basic manipulations on it to get you started:
SELECT CAST(CAST('Jan18'||TRIM(EXTRACT(YEAR FROM CURRENT_DATE)) AS CHAR(9)) AS DATE FORMAT 'MMMDDYYYY') AS BaseDate_
, CASE WHEN Col1 = 'CY'
THEN BaseDate_
WHEN Col1 = 'LY'
THEN ADD_MONTHS(BaseDate_, -12)
WHEN Col1 = 'LY-1'
THEN ADD_MONTHS(BaseDate_, -24)
ELSE BaseDate_
END AS DateModified_
FROM {MyDB}.{MyTable};
The EXTRACT() function allows you to take apart a DATE, TIME, or TIMESTAMP value.
You have you use TRIM() around the EXTRACT to get rid of the whitespace that is added converting the DATEPART to a CHAR data type. Teradata is funny with dates and often requires a double CAST() to get things sorted out.
The CASE statement simply takes the encoded values you suggested will be used and uses the ADD_MONTHS() function to manipulate the date. Dates are INTEGER in Teradata so you can also add INTEGER values to them to move the date by a whole day. Unlike Oracle, you can't add fractional values to manipulate the TIME portion of a TIMESTAMP. DATE != TIMESTAMP in Teradata.
Rob gave you an sql approach. Alternatively you can use ColdFusion to generate values for the columns you have. Something like this might work.
sampleDate = CreateDate(2010,4,12); // this simulates user input
if (year(sampleDate) is year(now())
col1Value = 'CY';
else if (year(now()) - year(sampleDate) is 1)
col1Value = 'LY'
else
col1Value = 'LY-' & DateDiff("yyyy", sampleDate, now());
col2Value = DateFormat(sampleDate, 'mmmdd');
Then you send col1Value and col2Value to your query as parameters.

Sql server convert date to 10 digit integer for comparison

I'm working with a database where dates are stored as 10 digit integers and where the user can query information within certain calendar date ranges. I was wondering what are the steps for converting a calendar date to a 10 digit integer for comparison with dates stored in a database.
I'm working with sql server 2000.
You need SELECT DATEADD(second, 1240494225, '19700101') to convert the number to a date and SELECT DATEDIFF(second, '19700101', #some_date) to go the other way.

Convert SQL server datetime fields to compare date parts only, with indexed lookups

I've been doing a convert(varchar,datefield,112) on each date field that I'm using in 'between' queries in SQL server to ensure that I'm only accounting for dates and not missing any based on the time part of datetime fields.
Now, I'm hearing that the converts aren't indexable and that there are better methods, in SQL Server 2005, to compare the date part of datetimes in a query to determine if dates fall in a range.
What is the optimal, indexable, method of doing something like this:
select * from appointments
where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
The best way to strip the time portion of a datetime field is using datediff and dateadd functions.
DateAdd(day, datediff(day,0, MydateValue), 0)
This takes advantedge of the fact that SQL Server stores dates as two integers, one representing the number of days since day "0" - (1 jan 1900), and the second one which represents the number of ticks (each tick is about 3.33 ms) since midnight (for the time) *.
the formula above simply has to only read the first integer. There is no conversion or processing required, so it is extremely fast.
To make your queries use an index... use this formula on the input filtering parameters first, or on the "other" side of the equal sign from the tables date time field, so that the query optimizer does not have to run the calculation on every datetime field in the table to determine which rows satisfy the filter predicate. This makes your search argument "SARG-able" (Search ARGument)
Where MyDateTimeColumn > DateAdd(day,
datediff(day,0, #MydateParameter), 0) -- SARG-able
rather than
Where DateAdd(day, datediff(day,0,
MyDateTimeColumn ), 0) > #MydateParameter -- Not SARG-able
* NOTE. Internally, the second integer (the time part) stores ticks. In a day there are 24 x 60 X 60 X 300 = 25,920,000 ticks (serendipitously just below the max value a 32 bit integer can hold). However, you do not need to worry about this when arithmetically modifying a datetime... When adding or subtracting values from datetimes you can treat the value as a fraction as though it was exactly equal to the fractional portion of a day, as though the complete datetime value was a floating point number consisting of an integer portion representing the date and the fractional portion representing the time). i.e.,
`Declare #Dt DateTime Set #Dt = getdate()
Set #Dt = #Dt + 1.0/24 -- Adds one hour
Select #Dt
Set #Dt = #Dt - .25 -- Moves back 6 hours
Select #Dt`
Converting numeric types to string values (a type of Boxing) is not the best performing method of doing what you are looking for. Its not really about index-able, because the actual column type is date time.
If you are looking for the best way query for dates, then your example is right, but you may want to take into account the 3 ms precision difference in MSSQL. It can mean that records from one day can show up in another day's result.
This
select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
Should be this
select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<='08-14-2008 23:59:59.996'
It's correct - doing the conversion will execute the conversion for every row queried. It's better to leave the date columns as dates, and pass in your where clauses as dates:
select * from appointments where appointmentdate between
'08/01/2008' AND '08/16/2008'
Note: Leaving off the time means midnight (00:00.000), so you will include all times for 08/01, and all times from 08/15, and anything that is exactly 08/16/2008 00:00:00
Have a computed persisted column calculate the expression you need. If columns are computed and persisted, they can also be indexed.
There is also the way described at http://www.stillnetstudios.com/comparing-dates-without-times-in-sql-server/
SELECT CAST(FLOOR(CAST( getdate() AS float )) AS datetime)