SQL Server: compare dates by only matching month and day - sql

I have a stored procedure that fetches records based on dates matching a date input which works fine so far.
Both the dates in the table and my input date are formatted as datetime.
Instead of comparing the full dates I would like to change this so that it only compares month and day so that it works with any year for the input.
Example:
A date in the table is saved as 2013-04-30 and my input date is 2014-04-30.
What I want is that the stored procedure still returns that record independent of the year as long as month and day match.
My stored procedure:
ALTER PROCEDURE [dbo].[FetchDays]
#inputDate datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT dateID,
dayDT,
countries,
regions
FROM DaysDT
WHERE dayDT = #inputDate
FOR XML PATH('daysFixed'), ELEMENTS, TYPE, ROOT('root')
END
Many thanks for any help with this, Mike.

You can do something like this ;)
ALTER PROCEDURE [dbo].[FetchDays]
#inputDate datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT dateID,
dayDT,
countries,
regions
FROM DaysDT
WHERE
DAY(dayDT) = DAY(#inputDate) --Extract and compare day
AND MONTH(dayDT) = MONTH(#inputDate) --Extract and compare month
FOR XML PATH('daysFixed'), ELEMENTS, TYPE, ROOT('root')
END

Try this:
WHERE datepart(day, dayDT) = datepart(day,#inputDate)
AND datepart(month, dayDT) = datepart(month,#inputDate)
This will compare the date and month parts of your overall date, without checking the year.

I have been needed this type of requirement in past. I have used this solution and it worked for me as I wanted.
SELECT * FROM yourTableName
WHERE DATE_FORMAT(yourColumnName, '%m-%d') = DATE_FORMAT('yourValue', '%m-%d') and yourOtherCondition;

Related

Show only full weeks - SQL

how could I display only full weeks from my dataset? So if my week starts on Monday 1st of August to the 14th, that would be considered a full week. Whereas the one starting on the 8th is considered half and I'd like not to show it.
Many thanks in advance!
Table name:RRA
date column: seriesdate
My answer assumes that you want to select rows where the seriesdate value is in a week that is not the current week.
Assuming that your seriesdate column is indexed then a SARGable (i.e. fast) way to implement this filter is to just exclude rows with dates after the start-of-the-current-week. Like so...
Also...
Note that CURRENT_TIMESTAMP (the ISO SQL equivalent of SQL Server's GETDATE()) uses the database server's local timezone which might not be the timezone used by your data.
If so, replace DECLARE #now datetime2(7) = CURRENT_TIMESTAMP; with a date/time-literal like DECLARE #now datetime2(7) = '2022-08-10 12:34:56';
Note that most SQL Server setups will default to DATEFIRST 7 (Sunday).
SET DATEFIRST 1; -- https://learn.microsoft.com/en-us/sql/t-sql/statements/set-datefirst-transact-sql
DECLARE #now datetime2(7) = CURRENT_TIMESTAMP; -- or '2022-08-10 12:34:56'
-- https://stackoverflow.com/questions/7168874/get-first-day-of-week-in-sql-server
DECLARE #startOfThisWeek date = DATEADD( day, 1 - DATEPART( weekeday, #now ), #now );
SELECT
q.*
FROM
[RRA] AS q
WHERE
q.[seriesdate] < #startOfThisWeek

SQL Server end of month

Suppose there is one date in int format 20191229, I want to find end of month and check if it's end of month is of 31 days or 30 days in SQL Server
You can try this from the reference. The given answer will not work for the integer data type but it will work in the varchar datatype date value. Storing Date values in integer is not a good idea, so as suggested by Larnu change the data type in either date or varchar.
SELECT
Day(EOMONTH(Cast('20191229' as Date))) end_of_month;
If you want the amount of days within a month, as you need the days as an integer, you should go for this. This is the most robust built, but also the more complex one, as to make sure the Integer value is processed correctly:
SELECT DATEPART(DAY,EOMONTH(CAST(CAST('20191229' AS NCHAR(8)) AS DATE))) AS Days
Result:
Days
31
If you want to add an IF evaluation to your selected date(s), you can do this by add an IIF-clause where it evaluates whether or not the end of month is 31 or not. If you want to use a columnname instead of the date, just substitute #Date with the columnname. I've just added the variable #Date instead of '20191229' to make it more illustrative/understandable. You can change the True/false descriptions to whatever you like in the query.
DECLARE #Date AS int
SET #Date = '20191229'
SELECT
IIF (
DATEPART(DAY,EOMONTH(CAST(CAST(#Date AS NCHAR(8)) AS DATE))) = '31'
,'True'
,'False'
) AS Days
Output:
Days
True

Query Datetime Declaration

I'm having trouble with a Datetime column in a table while adding declaration on a stored procedure.
I want to set #EventTime as a day of the week without modifying the column..
More like a catch.
For example:
declare #EventTime datetime
set #EventTime = (select EventTime
from _LogClients
where ClientID = #ClientID)
if (#EventTime like '%2-2%) -- As a day of a week not as a numerical date.
- - Datetime preview:2019-01-22 17:47:00
Any help regarding that matter?
Note:
The EventTime is used on a Stored Procedure which runs on a certain event that occur.. However, the database is a Game one, so the logger is based on the server files, I need to know if I'm able to make the EventTime declaration able to read the datetime from the column as weekday in order to execute a certain query for that day (Not SQL Agent based though.. that's a different story).
I'm not sure from your question if you are trying to get the numerical representation of the actual day of the week (like Sunday would be "1", Monday as "2", etc.. ) or if you just need the day of the week as a word from a date.
Here is your code modified to use the word for the day of the week (please note you could have used the DateName within the select statement but then you'd need to change the type of #EventTime to a nVarchar() or nchar) :
declare #EventTime datetime
set #EventTime = (select EventTime
from _LogClients
where ClientID = #ClientID)
if (DATENAME(dw,#EventTime) like '%Tuesday%)
If you wanted the numerical equivalent use:
if (DATEPART(dw,#EventTime) = '1' -- Testing for Sunday day name

Concatenate two date parts

I'm trying to build a report based on a ticketing system we use. I'm quite new to SQL and just getting my head around it but the issue I am facing at the moment is trying to join two fields into a date. The data in the table is in displayed as Month_Number and Year_Number
I need to do a comparison with a datetime field to see if it is between the date range. I've searched a fair bit about concatenating the two fields I have into a date but unfortunately have come up short.
You can simply do this to concatination for youe Month & Date Part.
declare #month varchar(10);
declare #year varchar(10)
set #month = 5
set #year = 2014
You can choose whatever you feel for you is the best
select #month+'-1-' +#year as Your_Date
select '1-'+#month+'-' +#year as Your_Date
select #year+'-'+#month+'-1' as Your_Date
Output
5-1-2014
1-5-2014
2014-5-1
To Retrieve the date from your Table in SQL you can do like this
select month_number+'-1-' +year_number as Your_Date
from table_name
If you want to change the style of the displaying output then you can use Convert Function

Creating a list of all the dates between a range and then insert it

I have a problem were I need to insert a set of dates (one row for each date) that come from a date range that comes in to me as an ical format. I also need to insert the date if the date does not exist.
I'm happy manipulating the date formats so converting the incoming 20131201T000000 to smalldatetime is ok and I can build the SQL Not Exits as separate bits but how do I go about listing all the dates between 20131201 and 20140101 and then go about inserting them into the table if Not Exists along with some other data.
One idea I had would be to count the days using DateDiff which will give me a total number of days in the range and then I could DateAdd one day at a time and insert for each date until the DateDiff total is reached. However, it seems to be that its a very messy and long winded way to go about it and I would find it challenging to say the least.
Is there another method that someone could walk me through or point me in the right direction of?
In my opinion you are much better off letting SQL Server determine the set of dates that are missing than to create a set of dates, then pull back all of the existing dates in the table to compare them to your set, then insert the ones that don't match. By doing this you are taking what SQL Server is really, really good at, tossing it in the mud, and re-inventing a wheel that is now quite non-circular.
So I suggest you do this in SQL Server.
Imagine you have an existing table with some dates:
CREATE TABLE dbo.MyTable(TheDate DATE);
And it has some existing days in the specified range:
INSERT dbo.MyTable(TheDate) VALUES
('20131203'),('20131205'),('20131209'),('20131230');
You can easily derive a set without using loops as follows.
CREATE PROCEDURE dbo.GenerateDates
#start CHAR(17),
#end CHAR(17)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #s DATE = LEFT(#start, 8), #e DATE = LEFT(#end, 8);
DECLARE #d SMALLINT = DATEDIFF(DAY, #s, #e);
;WITH x(d) AS
(
SELECT TOP (#d) DATEADD(DAY, number, #s)
FROM master..spt_values
WHERE type = N'P' ORDER BY number
)
-- INSERT dbo.MyTable(TheDate)
SELECT d FROM x WHERE NOT EXISTS
(SELECT 1 FROM dbo.MyTable WHERE TheDate = x.d);
END
GO
Sample usage:
EXEC dbo.GenerateDates
#start = '20131201T000000',
#end = '20140101T000000';
When you are happy this is giving the output you expect, alter the procedure and uncomment the INSERT.
(Also it would be best if you just pass date values from your app, instead of these 17-character strings, but I was working with what you have.)
Well lets see. You have a date called beginDate and date called endDate. Lets get all they days between those dates into list:
List<DateTime> betweenDates = new List<DateTime>();
var currentDate = beginDate;
while(currentDate <= endDate)
{
betweenDates.Add(currentDate);
currentDate = currentDate.AddDays(1);
}
Then lets fetch all the rows that are already in database:
// var datesInDb = SELECT DATE FROM TABLE_X WHERE DATE BETWEEN (beginDate, EndDate);
Now we have dates from database and all the dates that should be in database. Lets substract dates from database from our betweenDates
var datesWhichShouldBeInsertedIntoDB = betweenDates.Any(day => datesInDb.Contains(day) == false);
then insert datesWhichShouldBeInsertedIntoDB