Run a function as today's date - c#

I have a query below that calls on a stored function. In the function you will see I need to declare a start date (#startdate) and an end date (#End date). These queries will be used inside a C# program that will run via windows task scheduler. The idea of this is to pull reports for the sales info each day and auto email it at night as part of nightly reports. Because of this I will need to assign #startdate to "today's" date. For example if the program is auto run today, I need sales info for 1/29/13 00:00 through 1/29/13 23:00. Tomorrow when it's run I'll need sales infor for 1/30/13 00:00 through 1/30/13 23:00. Etc. I am using the dateadd datediff in my other queries for the report, however this is the only query referencing a stored function. How would I accomplish the same thing in a stored function?
Here is my query calling a Stored Function:
SELECT
SUM(QTY) AS Discounts
FROM
dbo.fFinancialDataFull('Date Range Report', #startdate , #enddate, '1', '1', 'ALL', 'ALL', 'ALL', 'ALL', '1', '1', '1', '1', '1') AS fFinancialDataFull_1
WHERE
(ReportCategoryID = 62)) AS unlimitedtbl

It is difficult to tell if you want to generate the date before your current query or inside of the function.
If you want to do it before you call the function. You can easily use:
DECLARE #startdate AS DATETIME;
DECLARE #endDate AS DATETIME;
--- code that will work on any version of SQL Server
SET #startdate = DateAdd(day, DateDiff(day, 0, getdate()), 0)
SET #enddate = DateAdd(day, DateDiff(day, 0, getdate()), 0)
+ CAST('23:59:59' as datetime)
-- SQL Server 2008+ code with DATE datatype
SET #startdate = CAST(CAST(GETDATE() AS DATE) as datetime);
SET #enddate = CAST(GETDATE() AS DATE) + CAST('23:59:59' as datetime);
SELECT SUM(QTY) AS Discounts
FROM dbo.fFinancialDataFull('Date Range Report', #startdate , #enddate, '1', '1',
'ALL', 'ALL', 'ALL', 'ALL', '1', '1',
'1', '1', '1') AS fFinancialDataFull_1
WHERE ReportCategoryID = 62
The start date will be at midnight and the end date will be the current date minus one second. (See SQL Fiddle with Demo)
If you are looking for a way to easily generate today's date at midnight and then an enddate of today's date with the time 23:59:59, then you could create a Table-Valued Function.
This type of function can return both the startdate and enddate based on a value that you pass in.
If it is possible, then I would alter your current function to accept one date parameter, then inside of that function you can call a new function that will return the dates.
The new function will be similar to this:
create function dbo.GetStartEndDates
(
-- pass in the date
#dt datetime
)
RETURNS #dates table
(
StartDate datetime,
EndDate datetime
)
AS
BEGIN
insert into #dates
select CAST(CAST(#dt AS DATE) as datetime) startdate, -- returns yyyy-mm-dd 00:00:00.000
CAST(#dt AS DATE) + CAST('23:59:59' as datetime) enddate -- returns yyyy-mm-dd 23:59:59.000
return
END
Then your current function would include:
alter function dbo.fFinancialDataFull
(
--your list of parameters
--replace the start/end date with
#dateValue datetime
)
returns table...
as
begin
select *
from yourtable
cross apply dbo.GetStartEndDates(#dateValue) d -- this will return both start/end date
end
You could then use the start/end date in the rest of your query.
When you are calling your current function you would pass in getdate() or whatever datetime as the :
select *
from dbo.fFinancialDataFull(param1, param2, getdate(), etc, etc).

To get the date you can use the following SQL instead of a function:
CAST(CONVERT(VARCHAR,GETDATE(),1) AS DATETIME)
Substituting 1 with whatever format you want to work with from the chart on the MSDN

If you just want todays date without the time aspect simply:
Convert(Date,GetDate())
You can do the same to any other DateTime value and check equality and it will be true if they occurred at any point on the same day.

Related

C# sequence number issue in database

I have a column in the database table i.e. transaction Id. Its data type is var char(50). Now I want to save a row by combining the current date with a sequential number generated.
For Example 10/9/2016 is the date so first transaction is saved like 10920161 and the next one like 10920162 and so on. The sequential number is reset to 1 after every day.
How can I do this?
In SQL Server, it can be as simple as:
transactionId =
CONCAT(DATEPART(MONTH, GETDATE()),
DATEPART(DAY, GETDATE()),
DATEPART(YEAR, GETDATE()),
(SELECT COUNT(1)
FROM tableName
WHERE CONVERT(DATE, dateColumn) = CONVERT(DATE, getdate())) + 1)
Get the Number of transactions for that date, and add one to it. Concat that with a formatted string of Today's Date.
If you already have 3 records for today's date, the result would be:
100920164
Running SQL-Fiddle
Edit: EF suggested snippet:
string dateStr = DateTime.Today.ToString("Mdyyyy");
DateTime todayMidnight = DateTime.Today;
DateTime tomorrowMidnight = DateTime.Today.AddDays(1);
obj.transactionId = dateStr +
context.tableName.Count(x=> x.dateColumn >= todayMidnight
&& x.dateColumn < tomorrowMidnight) + 1;

Cannot convert datetime to string SQL

I want to convert date time to string. In my SQL query, I have a date "2016/06/15". With this date, I am subtracting it one month "2016/05/15".
I got this part working. However, when I am trying to convert it to a string (varchar or nvarchar), I encounter the following exception. Conversion failed when converting date time from character string. I am not sure how to fix this, help will be appreciated.
Here is my query
Declare #date as datetime
Set #date = GetDate()
print #date
Declare #dateMinusOneMonth as datetime
Set #dateMinusOneMonth = GetDate()
Set #dateMinusOneMonth = Convert(nvarchar, Convert(nvarchar(3), DateAdd(month, -1, #date)), 101)
print #dateMinusOneMonth
You are declaring #dateMinusOneMonth as datetime. Do it like this:
Declare #dateMinusOneMonth as nvarchar(20)
Set #dateMinusOneMonth = Convert(nvarchar, Convert(nvarchar(3), DateAdd(month, -1, #date)), 101)
#dateMinusOneMonth is of type datetime and you are trying to assign it varchar value which is not valid.
You can convert it in print like below
Set #dateMinusOneMonth = DateAdd(month, -1, #date)
print Convert(nvarchar, Convert(nvarchar(3), DateAdd(month, -1, #dateMinusOneMonth)), 101)
Lets first focus on transforming it to VARCHAR/NVARCHAR. Just pass the variable like this:
DECLARE #Time DATE
SET #Time = CAST(DATEADD(MM, -1, GETDATE() ) AS DATE )
SELECT CAST(#TIME AS VARCHAR(10) )
See how easy that was?
Result: 2016-05-14
Please note that your DB may be set up differently, and you should test or format the dates correctly.
Lastly, if you use TRY_CONVERT(), the answer will return a NULL instead of failing the entire code.
You can do it all in one line easily. also I don't like having to look up 101, 102,113, etc for date string formats with convert. seeing you mention c# if you are on SQL 2012 or newer just use FORMAT like you would in c#.
PRINT FORMAT(DATEADD(MONTH,-1,GETDATE()), 'yyyy/MM/dd')

DATEADD in dd-MM-yyyy format

I am using SQL Server 2005, I am getting date from user in the format dd-MM-yyyy and limit of up to 5 days so user can see result upto +-5 days.
I tried a lot but unable to :
Convert dd-MM-yyyy into yyyy-MM-dd
Add days to dd-MM-yyyy in a SQL query
My SQL query is:
SELECT
(convert(varchar(10), OrderDate, 105)) AS OrderDate
FROM
[Products] p
WHERE
((convert(varchar(10), OrderDate, 105)) BETWEEN
(DATEADD(dd, -3, '22-01-2014'))
AND
(DATEADD(dd, 3, '22-01-2014'))
)
In above query, suppose user enters 22-01-2014 as date and 3 as flexibleDays (so user can see result from 19-01-2014 to 25-01-2014).
How can I add days in format dd-MM-yyyy in above SQL query?
I would recommend NOT use overuse the date conversion to and from strings! If you convert a DATE or DATETIME to a string - of course you cannot add days to it - it's a string now after all!
So if you already have a DATE or DATETIME column - use it and leave it's datatype alone!
Try code something like this:
-- define inputs from user - a date in string format, and a number of days
DECLARE #UserEntered VARCHAR(20) = '22-01-2014'
DECLARE #FlexiDays INT = 3
-- declare some helper variables - user input as DATE, from and to dates
DECLARE #UserEnteredDate DATE
DECLARE #FromDate DATE
DECLARE #ToDate DATE
-- determine the DATE the user entered, and the resulting "From" and "To" dates (as DATE)
SELECT #UserEnteredDate = CONVERT(DATE, #UserEntered, 105)
SET #FromDate = DATEADD(DAY, -1 * #FlexiDays, #UserEnteredDate)
SET #ToDate = DATEADD(DAY, #FlexiDays, #UserEnteredDate)
-- do your query without any messy conversions!
SELECT
OrderDate
FROM
[Products] p
WHERE
OrderDate BETWEEN #FromDate AND #ToDate
Try this function
CREATE FUNCTION SUBTRACT_DAYS( #date AS DATETIME, #days AS INT )
RETURNS DATETIME
BEGIN
RETURN DATEADD(dd, -#days, #date);
END
CREATE FUNCTION ADD_DAYS(#date AS DATETIME, #days AS INT )
RETURNS DATETIME
BEGIN
RETURN DATEADD(dd, +#days, #date);
END
SELECT dbo.SUBTRACT_DAYS('2014-01-22', 3),dbo.ADD_DAYS('2014-01-22', 3)
OP
Start End
2014-01-19 00:00:00.000 2014-01-25 00:00:00.000
Try this:
DECLARE #UserEntered VARCHAR(20) = '22-01-2014'
DECLARE #FlexiDays INT = 3
DECLARE #UserEnteredDate DATE
DECLARE #FromDate DATE
DECLARE #ToDate DATE
dates (as DATE)
SELECT #UserEnteredDate = CONVERT(DATE, #UserEntered, 105)
SET #FromDate = DATEADD(DAY, -1 * #FlexiDays, #UserEnteredDate)
SET #ToDate = DATEADD(DAY, #FlexiDays, #UserEnteredDate)

Week of year translation between c# and SQL

So I'm at the end of a long programming binge and I have one logical hurdle left to get over. My application presents KPIs for quote requests. The business leads have asked for these KPIs to be broken down by week, and I imagine when that is complete the request will come for a breakdown by month. I've figured this out in my SQL queries:
SELECT qpid FROM cpkpis WHERE DATEPART(ww, qpvalidfrom)=13 GROUP BY qpid;
Which will give my a list of qpids to compute a total from and provide actual primary keys for drill down.
What I can't get my head around is how to get an enumeration of weeks of the year form my C# code. I've looked the GregorianCalandar Class and specifically the GetWeekOfYear Method but I'm having trouble coming up with an enumeration of those values.
My question then is this: given a date range [lets say 2013-01-14 through 2013-04-10] how would I get an enumeration of the weeks of the year as ints between the start date and end date?
To help with with this task and the other requirements you're anticipating, you need a date table. IMHO the hardest thing to do in a database is to query data that isn't there.
You can query the date table:
Select Distinct DatePart(ww, dateField) as WeekNo
from DateTable
where dateField between '2013-01-14' and '2013-04-10';
From C#, an iterator is probably the simplest option:
public static IEnumerable<int> WeekNumbersBetween(
DateTime startDate,
DateTime endDate,
Calendar calendar = null,
CalendarWeekRule weekRule = CalendarWeekRule.FirstDay,
DayOfWeek firstDayOfWeek = DayOfWeek.Sunday)
{
if (calendar == null)
{
calendar = new GregorianCalendar();
}
DateTime week = startDate;
while (week <= endDate)
{
yield return calendar.GetWeekOfYear(week, weekRule, firstDayOfWeek);
week = week.AddDays(7);
}
}
The default values for the weekRule and firstDayOfWeek parameters should match the default settings in SQL. If your settings are different, you'll need to specify the correct values.
In T-SQL you could use something like:
DECLARE #StartDate DATE = '2013-01-14';
DECLARE #EndDate DATE = '2013-04-10';
WITH weekcte AS
(SELECT DATEADD(dd, -1, DATEADD(wk, DATEDIFF(wk, 0, #StartDate), 0)) AS DateValue
UNION ALL
SELECT DATEADD(wk, 1, DateValue)
FROM weekcte
WHERE DATEADD(wk, 1, DateValue) <= #EndDate )
SELECT DATEPART(ww, w.DateValue) AS 'Week No'
FROM weekcte AS w;

How to return a birthday from an SQL statement, given a person's age

I'm trying to create a filter in ASP.net, where a user can select a certain age and an SQL statement is to return all users who are currently this age, based on a 'DOB' (date of birth) field.
So, for example, lets say that I have a variable age which currently holds 23. I've got a field in the database called 'DOB', of type 'date'. How would an SQL statement be written to return all records whose date of birth indicate that they are 23? The DOB format is in YYYY-MM-DD.
Thanks
WHERE YEAR(GETDATE() - DATEPART(dy, DOB) + 1) - YEAR(DOB) = 37
just change 37 to 23 on your end or better yet use a variable
Here is an example you can run
CREATE TABLE #test(DOB DATETIME)
INSERT #test VALUES('19701127')
INSERT #test VALUES('19741127')
INSERT #test VALUES('19740227')
INSERT #test VALUES('19761127')
INSERT #test VALUES('19761127')
INSERT #test VALUES('19701127')
SELECT * FROM #test
WHERE YEAR(GETDATE() - DATEPART(dy, DOB) + 1) - YEAR(DOB) = 37
1974-11-27 00:00:00.000
1974-02-27 00:00:00.000
You can also use this more convoluted WHERE clause
SELECT *
FROM #test
WHERE DATEDIFF(YEAR, DOB, GETDATE()) -
CASE WHEN DATEPART(mm,DOB) > DATEPART(mm,GETDATE())
OR (DATEPART(mm,DOB) = DATEPART(mm,GETDATE())
AND DATEPART(dd,DOB) > DATEPART(dd,GETDATE()))
THEN 1 ELSE 0 END = 37
Yet another way to achieve this.
DECLARE #age int
DECLARE #dob1 date
DECLARE #dob2 date
SELECT #age = 23
SELECT #dob1 = DATEADD(year, -#age, getdate())
SELECT #dob2 = DATEADD(year, 1, #dob1)
SELECT * FROM <table>
WHERE DOB BETWEEN #dob1 AND #dob2
I'm going to assume that both the database column and the age variable hold date/time data rather than strings. I'm also going to assume that the [DOB] values are guaranteed not to have a time component.
You're missing one datum from your specification: the reference date. In other words, given the age 23, and a bunch of birthdays, you want to know which people are 23 on a given date. You might assume that this would be the current date, but here we'll generalize this to a variable.
Those born on Feb 24 1989 are 23 today; anyone born later is younger. Those born on Feb 24 1988 or earlier are 24 or older today. The desired range is therefore Feb 25, 1988 to Feb 24 1989.
DECLARE #age int
DECLARE #referenceDate date
DECLARE #rangeEnd date
DECLARE #rangeBegin date
SELECT #age = 23
SELECT #referenceDate = GETDATE()
--2012-02-24
SELECT #rangeBegin = DATEADD(day, 1, DATEADD(year, -#age-1, #referenceDate))
--1988-02-25
SELECT #rangeEnd = DATEADD(year, -#age, #referenceDate)
--1989-02-24
-- EDIT: this expression is incorrect; thanks to ypercube for catching the bug
-- SELECT #rangeBegin = DATEADD(day, 1, DATEADD(year, -1, #rangeEnd))
SELECT * FROM <table>
WHERE DOB BETWEEN #rangeBegin AND #rangeEnd
Those who where born the same date as today, exactly #age years ago:
WHERE dob = DATEADD( year, - #age, GETDATE() )
If the DOB field is a date field, you can do some date comparisons to get what you want.
SELECT user, DOB FROM yourtable
WHERE MONTH(CURDATE())=MONTH(DOB) AND
DAY(CURDATE())=DAY(DOB) AND YEAR(CURDATE())-YEAR(DOB)=23;

Categories