I have an SSRS Date/Time parameter generated from a shared dataset query against a SQL Server datetime field. The parameter displays correctly in a report textbox but it will not work in an embedded dataset query, even against the same table that the datetime value was generated from.
In order to use the parameter for a dataset query I have to parse both sides of a where clause to get it to work in Preview in SSDT:
(convert(varchar,invoice.snapshot_datetime,120)) = (convert(varchar,#snapshotdatetime,120))
This is tremendously inefficient.
How can I get my where clause to work without parsing the invoice.snapshot_datetime column?
Server Details
The SQL Server Language is English (United States).
SQL Server dateformat is mdy (from dbcc useroptions).
Getdate() returns '2015-05-20 10:27:56.687' in SSMS
Assuming your date range is between 1900-01-01 and 2079-06-06 you can cast to SmallDateTime to truncate the seconds out of your datetime variable:
DECLARE #DateTime datetime
SET #DateTime = CAST(CAST(#snapshotdatetime as SmallDateTime) as DateTime)
(thanks to t-clausen.dk for his answer here)
Now, since your actual column is of type DateTime, it does keep seconds (and milliseconds), and you will need to eliminate them as well.
However, using functions on your column will prevent the SQL Server from using any indexes you might have on this column, so a better approach would be to use a DateTime range:
DECLARE #FromDateTime datetime, #ToDateTime datetime
SET #FromDateTime = CAST(CAST(#snapshotdatetime as SmallDateTime) as DateTime)
Since the cast will round the minutes of the small date time up if it's over 29.998 seconds, and down if it's below 29.999 seconds. You always want to round down since it's From datetime, you need to cheke if you need to decrease a minute:
IF datepart(second, #snapshotdatetime) > 29
OR (datepart(second, #snapshotdatetime) = 29
AND datepart(millisecond, #snapshotdatetime) > 998)
SET #FromDateTime = DATEADD(minute, -1, #FromDateTime)
SET #ToDateTime = DATEADD(minute, 1, #FromDateTime)
and then, in your where clause, use this:
invoice.snapshot_datetime <= #FromDateTime
AND invoice.snapshot_datetime >= #ToDateTime
If you haven't found solution yet, try this:
select (convert(varchar,GETDATE(),112))
it will return 20180206 (yyymmdd)
Related
ALTER PROCEDURE [dbo].[AccountsData]
#Start_Date datetime,
#End_Date datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT
a.Customer_AC_No, a.Customer_Name, a.Product_Code,
a.Product_Description, a.Sales_Person, c.HSID
FROM
(SELECT
Customer_AC_No, Customer_Name, Product_Code,
Product_Description, Sales_Person
FROM
View_Sales_Details
WHERE
([Week Ending] >=' #Start_Date') AND ([Sales Value] > 0)
GROUP BY
Customer_AC_No, Product_Code, Product_Description,
Customer_Name, Sales_Person) AS a
LEFT JOIN
(SELECT
Customer_AC_No, Product_Code
FROM
View_Sales_Details
WHERE
([Week Ending] >= '#End_Date') AND ([Sales Value] > 0)
GROUP BY
Customer_AC_No, Product_Code) AS b ON a.Customer_AC_No = b.Customer_AC_No
AND a.Product_Code = b.Product_Code
INNER JOIN
Hubspot.dbo.View_BPA_Cust_Data AS c ON a.Customer_AC_No = c.CustomerNo COLLATE Latin1_General_100_CI_AS
WHERE
b.Customer_AC_No IS NULL
ORDER BY
a.Customer_AC_No, a.Product_Code ASC
END
I am trying to pass the above date parameters to the SQL Server stored procedure above, but I keep getting this error
Msg 241, Level 16, State 1, Procedure AccountsData, Line 52
Conversion failed when converting date and/or time from character string.
Can some one please help. WeekEnding date is also in datetime format. Thanks
There are many formats supported by SQL Server for specifying a date&time as a string literal - see the MSDN Books Online on CAST and CONVERT. Most of those formats are dependent on what settings you have - therefore, these settings might work some times - and sometimes not.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
The recommendation for SQL Server 2008 and newer is to use DATE if you only need the date portion, and DATETIME2(n) when you need both date and time. You should try to start phasing out the DATETIME datatype if ever possible.
So in your case, either switch to using DATE as your parameter datatype (since you obviously don't use the time portion):
ALTER PROCEDURE [dbo].[AccountsData]
#Start_Date DATE,
#End_Date DATE
and then execute your stored procedure like this:
EXEC [dbo].[AccountsData] '2019-05-11', '2020-06-10'
or use this format to support DATETIME if you insist on keeping that:
EXEC [dbo].[AccountsData] '2019-05-11T00:00:00', '2020-06-10T00:00:00'
Your have an error in your select. You have change your query like this
DATEPART(wk, Ending)>=DATEPART(wk, #Start_Date) AND ([Sales Value] > 0)
DATEPART(wk, Ending)>=DATEPART(wk, #End_Date) AND ([Sales Value] > 0)
Using SQL Server 2016, I have a table that contains a column DateTime of type INT which contains a UNIX timestamp. So if I want to get all the rows where the timestamp is yesterday, I know I need to check if the timestamp is >= the timestamp for 'yesterday at 00:00' and <= 'yesterday at 23:59'.
How can I do this with SQL Server 2016?
Found a few examples but they where for MySQL. I did find this example below. But it throws an error, so I'm probably not using it correctly. Or actually, this might be MySQL as well...
WHERE [DateTime] <= DATEADD(day, -1, convert(day, GETDATE()))
Any help would be greatly appreciated!
Here's my solution that seems to work. Did a test manually where I checked if the timestamp was between 1596513600 and 1596599940, and got the same output from the Solution below:
Function to Convert Timestamp to datetime type (*adjusts for Local time):
CREATE FUNCTION dbo.fn_ConvertToDateTime (#Datetime int)
RETURNS DATETIME
AS
BEGIN
DECLARE #LocalTimeOffset BIGINT
,#AdjustedLocalDatetime BIGINT;
SET #LocalTimeOffset = DATEDIFF(second,GETDATE(),GETUTCDATE())
SET #AdjustedLocalDatetime = #Datetime - #LocalTimeOffset
RETURN (SELECT DATEADD(second,#AdjustedLocalDatetime, CAST('1970-01-01 00:00:00' AS datetime)))
END;
GO
SQL Statement:
SELECT *
FROM dbname.dbo.Tablename
WHERE dbo.fn_ConvertToDateTime([DateTime]) >= dateadd(day,datediff(day,1,GETDATE()),0)
AND dbo.fn_ConvertToDateTime([DateTime]) < dateadd(day,datediff(day,0,GETDATE()),0)
The Resulting output shows only Rows that contain a unix timestamp from Yesterday.
I have to query an SQL Server database and the table's values use Epoch time (an int. Here's an example - 1438005018). I am wondering how I can write a query so that I can say the following...
select
*
from
tablename
where
epochdate between 'yesterday at 12:00' and 'today at 12:00' --this is the part I'm not sure about.
Ideally, if it's easy, I'd like the query to use non-epoch logic as Epoch time confuses the crap out of me. Maybe there's a quick way of converting in SQL Server?
I posted a link above in the comments that may be a more practical solution if you're able to deploy functions in the database you're working with, but if you're only able to query, this is an option to try as well (this assumes SQL Server 2008 and above):
declare #todayepoch bigint, #yesterdayepoch bigint;
select #todayepoch =
cast((cast(dateadd(hour, 12,
cast(cast(sysutcdatetime() as date) as datetime)) as decimal(24,10))
- cast(cast('1970-01-01' as datetime) as decimal(24,10)))
*60.0*60.0*24.0 as int), -- + 18000, --Eastern time
#yesterdayepoch =
cast((cast(dateadd(hour, -12,
cast(cast(sysutcdatetime() as date) as datetime)) as decimal(24,10))
- cast(cast('1970-01-01' as datetime) as decimal(24,10)))
*60.0*60.0*24.0 as int) -- + 18000 --Eastern time
select #todayepoch, #yesterdayepoch
select
*
from
tablename
where
epochdate between #yesterdayepoch and #todayepoch
I used UTC above as a presumption of comparing based on UTC times, but you could also compare to your time zone, with the appropriate addition/subtraction of your time zone difference in seconds (e.g., add 18000 to each variable to get noon in Eastern Standard Time).
You can test your results by using http://www.epochconverter.com/ to compare your values in your variables.
You query would look like the following:
DECLARE #dt_from DATETIME;
DECLARE #dt_to DATETIME;
SELECT
#dt_from=DATEADD(HH,-12,CAST(FLOOR(CAST(GETUTCDATE() AS FLOAT)) AS DATETIME)), -- strip time of current UTC date/time, and subtract 12 hrs
#dt_to=DATEADD(HH,+12,CAST(FLOOR(CAST(GETUTCDATE() AS FLOAT)) AS DATETIME)); -- strip time of current UTC date/time, and add 12 hrs
SELECT
*
FROM
tablename
WHERE
epochdate BETWEEN DATEDIFF(s,'1970-01-01',#dt_from) AND DATEDIFF(s,'1970-01-01',#dt_to);
I am trying to generate dates for the whole year of 2012 in datetime format to store in a SQL Server table in a datetime column.
How is that done?
So start date would be 1/1/2012 until 31/12/2012 but in the correct format. I am assuming I should have 365 rows generated. Any idea?
CREATE TABLE DateTimeRange2012([Date] DATETIME NOT NULL)
GO
INSERT INTO DateTimeRange2012([Date])
SELECT DATEADD(day, Number, '20120101')
FROM master..spt_values
WHERE Number < 366 AND type = 'P'
Much more clear for keeping the values persisted?
Nice answer from Oleg Dok.
To expand upon his answer, here's a stored procedure that accepts a year and generates all of the dates for the year. This takes into account leap years.
CREATE PROCEDURE GenerateDates (#Year INT)
AS
SET NOCOUNT ON
DECLARE #FirstDate DATETIME
DECLARE #NoOfDates INT
SET #FirstDate = DateAdd(Year, #Year-1900, 0)
IF MONTH(DATEADD(Day, 59, #FirstDate))=3
SET #NoOfDates = 365
ELSE
SET #NoOfDates = 366
INSERT INTO DateTimeRange([Date])
SELECT DATEADD(day, Number, #FirstDate)
FROM master..spt_values
WHERE Number < #NoOfDates AND type = 'P'
One proviso. I believe that "spt_values" may not be supported and may be removed in future versions of SQL Server. However, I have read that it is being used in SQL Server 11 example code so perhaps it's not a worry just yet.
I am looking for a SQL Server function to return the minimum value for datetime, namely January 1, 1753. I'd rather not hardcode that date value into my script.
Does anything like that exist? (For comparison, in C#, I could just do DateTime.MinValue)
Or would I have to write this myself?
I am using Microsoft SQL Server 2008 Express.
You could write a User Defined Function that returns the min date value like this:
select cast(-53690 as datetime)
Then use that function in your scripts, and if you ever need to change it, there is only one place to do that.
Alternately, you could use this query if you prefer it for better readability:
select cast('1753-1-1' as datetime)
Example Function
create function dbo.DateTimeMinValue()
returns datetime as
begin
return (select cast(-53690 as datetime))
end
Usage
select dbo.DateTimeMinValue() as DateTimeMinValue
DateTimeMinValue
-----------------------
1753-01-01 00:00:00.000
Have you seen the SqlDateTime object? use SqlDateTime.MinValue to get your minimum date (Jan 1 1753).
As I can not comment on the accepted answer due to insufficeint reputation points my comment comes as a reply.
using the select cast('1753-1-1' as datetime) is due to fail if run on a database with regional settings not accepting a datestring of YYYY-MM-DD format.
Instead use the select cast(-53690 as datetime) or a Convert with specified datetime format.
Enter the date as a native value 'yyyymmdd' to avoid regional issues:
select cast('17530101' as datetime)
Yes, it would be great if TSQL had MinDate() = '00010101', but no such luck.
Here is a fast and highly readable way to get the min date value
Note: This is a Deterministic Function, so to improve performance further we might as well apply WITH SCHEMABINDING to the return value.
Create a function
CREATE FUNCTION MinDate()
RETURNS DATETIME WITH SCHEMABINDING
AS
BEGIN
RETURN CONVERT(DATETIME, -53690)
END
Call the function
dbo.MinDate()
Example 1
PRINT dbo.MinDate()
Example 2
PRINT 'The minimimum date allowed in an SQL database is ' + CONVERT(VARCHAR(MAX), dbo.MinDate())
Example 3
SELECT * FROM Table WHERE DateValue > dbo.MinDate()
Example 4
SELECT dbo.MinDate() AS MinDate
Example 5
DECLARE #MinDate AS DATETIME = dbo.MinDate()
SELECT #MinDate AS MinDate
It's not January 1, 1753 but select cast('' as datetime) wich reveals: 1900-01-01 00:00:00.000 gives the default value by SQL server.
(Looks more uninitialized to me anyway)
This is what I use to get the minimum date in SQL Server. Please note that it is globalisation friendly:
CREATE FUNCTION [dbo].[DateTimeMinValue]()
RETURNS datetime
AS
BEGIN
RETURN (SELECT
CAST('17530101' AS datetime))
END
Call using:
SELECT [dbo].[DateTimeMinValue]()
What about the following?
declare #dateTimeMin as DATETIME = datefromparts(1753, 1, 1);
select #dateTimeMin;
The range for datetime will not change, as that would break backward compatibility. So you can hard code it.