FUnctions on Datekey - sql-server

I want MonthName and MonthNumber from Datekey variable EX:20141217. I need output as
Month Name: December MonthNumber: 12
I tried to convert Datekey into DateTime variable using expression
convert(datetime,convert(varchar(10),InvoiceCreateDateKey,120))
and top of it I used Month function to get MonthNumber.
MONTH(convert(datetime,convert(varchar(10),InvoiceCreateDateKey,120)))
and this following expression for MonthName
DATENAME(m,convert(datetime,convert(varchar(10),InvoiceCreateDateKey,120)))
I want to know are there any other functions in sql that I can use other than this complicated expressions? I want to simplify those expressions. Using above expressions my sql query is taking very very long time to execute.

Do you have a date dimension table in you database? It would add a join but would eliminate function calls and clean up complicated expressions. You could store the format you want as a column in this table for each date and join on date key. They are also very useful for aggregating data by various time slices. I used this to start mine: http://www.codeproject.com/Articles/647950/Create-and-Populate-Date-Dimension-for-Data-Wareho but there are other ones out there as well

You could use SUBSTRING to get the 5th and 6th characters of the Datekey string.

You can use 112 conversion for full date name
datename(month, convert(date, convert(nvarchar(10),InvoiceCreateDateKey), 112))
Also you can use datepart for getting month number
datepart(M,convert(date, convert(nvarchar(10),InvoiceCreateDateKey), 112))

Related

How do I use GETDATE in a WHERE clause using single quotes?

How do I use GETDATE() in a WHERE clause using single quotes? I have the following script:
SELECT DISTINCT
pm_requisition.a_requisition
,pm_requisition.a_req_description
,pm_requisition.rq_position_loc
,pm_requisition.rq_status_of_emp
,pm_applicant_rec.a_applicant_no
,pm_applicant_rec.aq_status_of_appl
,pm_applicant_rec.aq_apply_date
FROM
pm_requisition
LEFT OUTER JOIN pm_applicant_rec
ON pm_requisition.a_requisition = pm_applicant_rec.a_requisition
WHERE
pm_requisition.rq_status_of_req NOT IN (N'6', N'7')
AND pm_applicant_rec.aq_status_of_appl = N'N'
AND rq_position_loc = '3300'
AND pm_applicant_rec.aq_apply_date = CAST(GETDATE()AS datetime2) --('2021-03-30 00:00:00.000')
The dataset does not yield any data using the GETDATE() clause, but if I use today's date (commented out) with single quotes I get the correct dataset. I obviously can't put single quotes around CAST(GETDATE()AS datetime2). Am I missing something simple?
The reason your query does not work is that GETDATE() returns the current date and time, not the current date. As a result, the last line will never match, as you are comparing a date only with a date and time.
Your solution CAST(GETDATE() AS DATE) works is because it removes the time, which means you are now comparing a date with a date.
If you simplify your SQL to something like this :-
SELECT TOP 1 aq_apply_date,
GETDATE() [GETDATE]
FROM pm_applicant_rec;
you will see a result like this, so two different values, and clear why they do not match :-
aq_apply_date GETDATE
----------------------- -----------------------
2021-04-04 00:00:00.000 2021-04-04 14:32:15.507
You might see something slightly different depending on the datatype used for aq_apply_date.

Creating SQL views in VBA

I am trying to create a view on a table called petients in my database. The table has five columns. One of them is the column which I want to keep patient admitted date. It data type is datetime so I want to create a query that filters the data in this table based on current date. For example I want create a view that shows only details of petients who have been recorded on the current day.
Here is my code:
CREATE VIEW [dbo].[recent petients]
AS
SELECT petient_id, name, age, contact
FROM [petients]
WHERE [date] = 'date.Today'
I am getting an error saying that failed to convert date to string. Can you help me to solve it, or where is my code wrong?
Your code looks like SQL Server code. If so, I would recommend:
SELECT petient_id, name, age, contact
FROM [patients]
WHERE [date] = CONVERT(date, GETDATE());
As a note: This version is much better than DATEDIFF() because it allows the use of an index on patient([date]).
If the "date" column has a time component, you can use:
WHERE CONVERT(date, [date]) = CONVERT(date, GETDATE())
Note that this is also index-safe in SQL Server.
I'm assuming you are using Transact-SQL from Microsoft SQL Server, but you should specify the sql dialect you are using.
Since the datetime field type generally includes also a time, it is better to use the DATEDIFF function: https://learn.microsoft.com/it-it/sql/t-sql/functions/datediff-transact-sql?view=sql-server-ver15
In your case, to consider only the record where date=today, the difference in days must be zero:
--SQL QUERY
WHERE DATEDIFF(day, GETDATE(), [date]) = 0
day identifies the element you want to consider the difference. A list of names or abbreviations can be found in the link
GETDATE() returns now datetime
2nd and 3rd arguments are the dates you want to make the difference between

How to compare column values to declared variable

I was asked this interview question.
--Without modifying the following code:
DECLARE #StartDateInput SMALLDATETIME = '1/1/2018',
#EndDateInput SMALLDATETIME = '1/1/2018'
--Modify the following query so that it will return contacts modified at any time on January 1st, 2018
SELECT *
FROM dbo.Contacts
I tried the following query but this was not correct. I'm sure that I'm supposed to use the #EndDateInput variable as well but I wasn't sure how to use it. I don't think that this is the right way to approach this in general either.
SELECT *
FROM dbo.Contacts
WHERE ModifiedDate = SMALLDATETIME
It looks like the question is probing your understanding of date and datetime types, namely that a date with a time is after a date without a time (if there is even such a thing; most timeless dates are considered to be midnight on the relevant date, which is a time too.. in the same way that 1.0 is the same thing as 1, and 1.1 is after 1.0)
I'd use a range:
SELECT *
FROM dbo.Contacts
WHERE ModifiedDate >= #StartDateInput AND ModifiedDate < DATEADD(DAY, 1, #EndDateInput)
Why?
This caters for datetimes that have a time component.
It doesn't modify the row data (always a bad idea, e.g. to cast a million datetimes to a date just to strip the time off, every time you query - precludes using an index on the column and is a massive waste of resources) just to perform the query.
It converts the apparent "end date is inclusive" implied by both #variables being the same, to a form that allows the exclusive behavior of < to work inclusively (adds a day and then gets rows less than the following day, thereby including 23:59:59.999999 ...)
The only thing I would say is that strictly, the spec only calls for one day's records, which means it's not mandatory to use the #EndDateInput at all. It seems logical to use it, but it could be argued that if the spec is that this query will only ever return one day, the #End variable could be discarded and a DATEADD performed on the #Start instead
It is saying "any time" meaning consider the time component. With T-SQL the only reliable way is to use >= and < range query (exclusive upper range):
SELECT *
FROM dbo.Contacts
WHERE ModifiedDate >= #StartDateInput and
ModifiedDate < dateadd(d, 1, #EndDateInput);
PS: Initial declaration of #StartDateInput and #ENdDateInput is not robust and probably by chance pointing to Jan 1st, 2018. If it were '1/2/2018' then it would be ambiguous between Jan 2nd and Feb 1st. Better use ODBC canonical and\or ISO 8601 strings like '20180101'.

SQL Server - Select between 2 dates of type DD/MM/YYYY

I want to query a datetime field using a range of dates provided in the format DD/MM/YYYY.
I know that to convert datetime to a DD/MM/YYYY format that I can use:
CONVERT(CARCHAR(10), ORDERDATE,103)`
And this works fine when querying a single date, eg:
SELECT DISTINCT
CONVERT(DATE, ORDERDATE),
CONVERT(CARCHAR(10), ORDERDATE,103)
FROM ORDERS
WHERE CONVERT(CARCHAR(10), ORDERDATE,103) = '19/10/2017'
Returns: 2017-10-19, 19/10/2017
However it does not work on a range of dates, eg:
WHERE CONVERT(CARCHAR(10), ORDERDATE,103) BETWEEN '17/10/2017' AND '19/10/2017'
Returns:
2014-02-05
2016-12-12
2013-04-30
I know there are hundreds of threads about SQL dates, but they all seem to be regarding reformatting the output and not preparing the input. Do I need to reformat my DD/MM/YYYY inputs?
To query a range of dates, use the DATE-datatype instead of VARCHAR.
If datatype of column ORDERDATE is DATETIME:
WHERE CONVERT(DATE, ORDERDATE) BETWEEN
CONVERT(DATE, '17/10/2017', 103) AND CONVERT(DATE, '19/10/2017', 103)
The conversion of ORDERDATE is only necessary if the start and end date are the same. (in this case, when no conversion is done, only dates with a time value of '00:00:00.000' will be returned)
EDIT:
To omit the conversion of ORDERDATE you can add the time to the dates and convert them to DATETIME instead of DATE, like this:
WHERE ORDERDATE BETWEEN
CONVERT(DATETIME, '19/10/2017 00:00:00') AND CONVERT(DATETIME, '19/10/2017 23:59:59.999');
Or even simpler, like suggested in #Used_By_Already's answer:
WHERE ORDERDATE >= '20171017' AND ORDERDATE < '20171020' --Note the end date is here +1 day
SQL Server date information should NOT be stored "in a format". If if they are literally stored in that format then they are NOT dates as far as the database is concerned (they are "strings" that look like dates) and you will have a nightmare to deal with if they are DD/MM/YYYY because they simply will not behave like dates should.
There are several specific data types in SQL Server for date/time information (datetime, datetime2, smalldatetime, date, time) but ALL of these do not store data in a human readable format at all. Instead they stored as groups of numbers, which will be displayed in a human readable manner, and in your case - by default - you are seeing then in DD/MM/YYYY format. A user in China might prefer to see a date in YYYY.MM.DD or in the USA as MM/DD/YYYY. This is possible because a human format is applied on top of the numbers that are stored before they get displayed.
So. In SQL Server there is a "safe" date literal in the form of 'YYYYMMDD' and this may be used without the need to CONVERT or CAST:
IF your [ORDERDATE] column is a date (or smalldatetime/datetime/datetime2) then this will work:
WHERE ORDERDATE BETWEEN '20171017' AND '20171019'
OR, you may explicitly convert a string to but you need a "style number" to be present to make these fully reliable. Style 103 for example is for DD/MM/YYYY
WHERE ORDERDATE BETWEEN CONVERT(date, '17/10/2017',103) AND CONVERT(date, '19/10/2017',103)
Although "between" has been used in the discussion above a far more reliable method of forming date ranges is to NOT use "between", instead do it this way:
WHERE ORDERDATE >= '20171017' AND ORDERDATE < '20171020'
With this pattern (note the second day is now +1) it does not matter which date precision is stored in the column. For example, see Bad habits to kick : mis-handling date / range queries

How do I convert date in Netezza to yyyymmdd from timestamp format?

How do I convert date in Netezza to yyyymmdd from timestamp format?
Use the below queries to convert to date format.
select TO_CHAR( DATE '2009-12-23 23:45:58','YYYY-MM-DD')
or
select TO_CHAR(TO_DATE( '2009-12-23 23:45:58','YYYY-MM-DD HH24:MI:SS'),'YYYY-MM-DD')
or
select TO_CHAR(current_timestamp,'YYYY-MM-DD')
Netezza has built-in function for this by simply using:
SELECT DATE(STATUS_DATE) AS DATE,
COUNT(*) AS NUMBER_OF_
FROM X
GROUP BY DATE(STATUS_DATE)
ORDER BY DATE(STATUS_DATE) ASC
This will return just the date portion of the timetamp and much more useful than casting it to a string with "TO_CHAR()" because it will work in GROUP BY, HAVING, and with other netezza date functions. (Where as the TO_CHAR method will not)
Also, the DATE_TRUNC() function will pull a specific value out of Timestamp ('Day', 'Month, 'Year', etc..) but not more than one of these without multiple functions and concatenate.
DATE() is the perfect and simple answer to this and I am surprised to see so many misleading answers to this question on Stack. I see TO_DATE a lot, which is Oracle's function for this but will not work on Netezza.

Resources