When I write this query
SELECT Convert(datetime,Convert(varchar,CAST(GETUTCDATE() AS DATE))+' '+
CONVERT(varchar, cast(meas_pain.datetime AS time))) FROM meas_pain
it works for me but when I use the same part in WHERE clause it gives error 'Conversion failed when converting date and/or time from character string.'
SELECT schedules.id
FROM meas_pain LEFT JOIN schedules ON schedules.id=meas_pain.schd_id
WHERE meas_pain.schd_id=9150 AND
Convert(datetime,(Convert(varchar,CAST(GETUTCDATE() AS DATE))+' '+
CONVERT(varchar, cast(meas_pain.datetime AS time)))) <
CONVERT(datetime,DATEADD(Minute,0,getutcdate()))
can anybody explain??
I am not sure why this error does not appear in your select statement, since I can reproduce the error using just
SET DATEFORMAT DMY;
SELECT CONVERT(DATETIME, CONVERT(VARCHAR,CAST(GETUTCDATE() AS DATE)))
Example of Error
You are relying on localised conversion settings, you should use explicit conversion, e.g.
SET DATEFORMAT DMY;
SELECT CONVERT(DATETIME, CONVERT(VARCHAR, CAST(GETUTCDATE() AS DATE), 111), 111)
By explicitly defining the date format to convert both to varchar and from varchar (111) you can avoid any implied conversions.
However, If your dates/times are stored as such there should be no need for all the conversion to and from varchar, this is just more chance for things to go wrong, and unnecessary work, you can simply add a time to a datetime. e.g.
DECLARE #Date1 DATETIME = DATEADD(HOUR, 1, GETUTCDATE()),
#Date2 DATETIME = DATEADD(DAY, 1, GETUTCDATE());
SELECT [Date1] = #Date1,
[Date2] = #Date2,
[Date1/Time2] = CAST(CAST(#Date1 AS DATE) AS DATETIME) +
CAST(#Date2 AS TIME);
From what I can gather from your query you are just trying to get results where the time of meas_pain.datetime is less that the current UTC time, regardless of date. So you should be able to simplify your query to just:
SELECT schedules.id
FROM meas_pain
LEFT JOIN schedules
ON schedules.id = meas_pain.schd_id
WHERE meas_pain.schd_id = 9150
AND CAST(meas_pain.[DateTime] AS TIME) < CAST(GETUTCDATE() AS TIME);
And remove further redundant conversions.
Simplified example on SQL Fiddle
ADENDUM
Apparently this time comparison is not what you are after (although it is what the query you have posted is doing), so I am assuming GETUTCDATE() is just for demonstration.
The conversion you are trying to perform is equivalent to this:
CAST(CAST(GETUTCDATE() AS DATE) AS DATETIME) + CAST(meas_pain.[DateTime] AS TIME)
Another example on SQL Fiddle using the above conversion
Related
I have value of column
datecolumn -> 2021-04-22T00:00:00.000
I want select using condition where like below:
SELECT * FROM 'tblDOISOAT' where datecolumn = strftime('%Y-%m-%d %H:%M:%S','2021-04-22 00:00:00')
I not get được value and i me met error 'Error: near "=": syntax error'. please help me
You have a typo, but your code works.
--------
dt
--------
2021-04-22T00:00:00.000
2021-04-23T01:00:00.000
--------
select strftime('%Y-%m-%dT%H:%M:%S.000', '2021-04-22 00:00:00') as 'datecode'
returns 2021-04-22T00:00:00.000
The query:
select dt from 't' where dt= strftime('%Y-%m-%dT%H:%M:%S.000', '2021-04-22 00:00:00')
returns the expected result: 2021-04-22T00:00:00.000
You forgot to include the correct formatting including T and .000 at the end.
remember that SQLite does not have a datetime data structure by default. You can read about SQLite data types here
If you are storing date/times as ISO-8601 text, you don't need to call strftime() to make comparisons. Just compare the 2 values:
select * from t1 where datecol = '2021-04-22T00:00:00.000';
The whole point of ISO-8601 strings is to make sure that date/time values compare lexicographically the same as temporally.
UPDATE: Issue was solved by #whosrdaddy. See comments below this question.
I am trying to resolve the following peculiar case: In a friend's Lazarus project, he tries to query an entry in SQLite. The asString()-method (in the procedure for displaying appointments) returns the proper date on Windows 64 Bit. On a 32 Bit operating system, however, only the first two digits are displayed ('16' instead of '28.02.2016'). What could be the reason?
This is the source code for initialising the form:
// Initialise Form
procedure TForm1.FormCreate(Sender: TObject);
begin
SQLite3Connection1.DatabaseName:='Kalender.sqlite';
SQLTransaction1.Database:=SQLite3Connection1;
SQLQuery1.Transaction:=SQLTransaction1;
// Create Table "tblTermine"
SQLQuery1.SQL.text := 'CREATE TABLE IF NOT EXISTS tblKalender (Datum DATETIME, Termin VARCHAR(10))';
SQLQuery1.ExecSQL;
SQLTransaction1.commit;
end;
There are two further procedures:
// Display Appointments
procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Clear;
SQLQuery1.Close;
SQLQuery1.SQL.text:='SELECT * FROM tblKalender';
SQLQuery1.Open;
while not SQLQuery1.Eof do
begin
// Should return 'dd.mm.yyyy'
ListBox1.Items.add(SQLQuery1.Fields[0].AsString+ ': ' + SQLQuery1.Fields[1].AsString);
SQLQuery1.Next;
end;
end;
// Save Appointment
procedure TForm1.Button2Click(Sender: TObject);
var Termin: string;
Datum: TDate;
begin
Termin:=Edit1.text;
if calendardialog1.execute then
Datum:=TDate(calendardialog1.date);
SQLQUERY1.close;
SqlQuery1.SQL.text:= 'Insert into tblKalender Values (:Datum, :Termin)';
SqlQuery1.ParamByName('Datum').AsDate:= Datum;
SqlQuery1.ParamByName('Termin').AsString:= Termin;
SqlQuery1.ExecSQL;
SqlTransaction1.Commit;
Button1.Click;
Edit1.Text := '';
end;
The intended output into the TListBox would be something like this.
you should convert first the DateTime to a Julian Date
function DateTimeToJulianDate(const Datum: TDateTime): Double;
and
SqlQuery1.SQL.text:= 'Insert into tblKalender Values (:Datum, :Termin)';
SqlQuery1.ParamByName('Datum').AsFloat := DateTimeToJulianDate(Datum);
...
SqlQuery1.ExecSQL;
to test and get the value use :
function TryJulianDateToDateTime(const AValue: Double; ADateTime: TDateTime):Boolean;
if TryJulianDateToDateTime(SQLQuery1.Fields[0].AsFloat,myDate)
then
ListBox1.Items.add(DateTimeToStr(myDate)+ ': ' + .....
else
ShowMessage('Not a valid Julian date');
Update
SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic
Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Double Test
procedure TForm1.Button3Click(Sender: TObject);
var
Datum : TDate;
myDate : TDateTime;
JulianDouble : Double;
begin
// uses ....,DateUtils
Datum := StrToDate('01.01.2013'); //German Culture settings
Memo1.Lines.Add('01/01/2013 = '+DateTimeToStr(Datum)+ ' TDate as Text');
Memo1.Lines.Add('01/01/2013 = '+FloatToStr(Datum) + ' TDate Double');
JulianDouble := DateTimeToJulianDate(Datum);
Memo1.Lines.Add('01/01/2013 = '+FloatToStr(JulianDouble) + ' Julian Double');
if TryJulianDateToDateTime(JulianDouble,myDate)
then
Memo1.Lines.Add('01/01/2013 = '+DateTimeToStr(myDate)+ ' TDate as Text')
else
ShowMessage('Not a valid Julian date');
end;
Output :
01/01/2013 = 01.01.2013 TDate as Text
01/01/2013 = 41275 TDate Double
01/01/2013 = 2456293,5 Julian Double
01/01/2013 = 01.01.2013 TDate as Text
Update-2 :
To write Delphi TDate Double to a SQLite Date field is wrong
Your comment shows me that you do not know the problems.
Of course you can directly write a Delphi Double value into a database field. And read it back to a TDateTime.
This will quickly lead to problems.
Examples:
SQLite:
These functions only work for dates between 0000-01-01 00:00:00 and
9999-12-31 23:59:59 (julidan day numbers 1721059.5 through 5373484.5).
For dates outside that range, the results of these functions are
undefined.
41275 Delphi TDate Double for 2013/01/01 is outside of above range !!
SQLite's own date functions can no longer be used.
Compute the current date.
SELECT date('now');
Compute the last day of the current month.
SELECT date('now','start of month','+1 month','-1 day');
Compute the date and time given a unix timestamp 1092941466.
SELECT datetime(1092941466, 'unixepoch');
Compute the date and time given a unix timestamp 1092941466, and compensate for your local timezone
SELECT datetime(1092941466, 'unixepoch', 'localtime');
Compute the number of days since the signing of the US Declaration of Independence.
SELECT julianday('now') - julianday('1776-07-04');
etc. etc.
Changing the date value with above functions will give you a double 2456293,5 for a Date 2013/01/01
If you now use unproved and pass it to a Delphi TDateTime it will be 3387/11/26).
This is not far from the maximum value of a TDateTimePicker.
which is 2958465.5 and means 9999/12/31
DateTimePicker1.DateTime := 2958465.5;
DateTimePicker1 9999/12/31
If one already know that it is wrong one should not use it up to a crash.
SQLite uses something called manifest typing which means that if you store values of (Delphi) type TDateTime, SQLite will store the underlying floating point value without warning or message, and offer you the value back so you won't notice that SQLite doesn't treat this as a date-time-value, unless you're trying to manipulate the value from SQL.
To counteract this, I use this bit of SQL code to convert Delphi TDateTime values to an actual SQL datetime:
datetime('1900-01-01','+'||(myDateField-2)||' day')
(see also here)
In an SSRS report, the user searches based on start date and end date.
The challenge is, as I discovered recently, he sometimes, not always, provides the time component while searching.
Currently, the filter is done like this:
if #pEndDate is null
SET #pEndDate = getdate()
SET #PEndDate = DateAdd(dd,1,#PEndDate)
SELECT ........
FROM .....
WHERE ( Createdon >= #PStartDate AND Createdon < #PEndDate)
This is fine when he searches without time (example - #PStartDate = 2/23/2015 and #PEndDate = 2/24/2015)
How should I structure the query to deal with the time portion when he provides it? (example - #PStartDate = 2/23/2015 15:00 and #PEndDate = 2/24/2015 15:00)
If this is answered elsewhere, please point me to it. Thank you.
If you just want to match the date part then there are lot options.
1) You can use the Date type for the parameter PEndDate and PStartDate to nullify the time part
2) You can use the Convert method to get only date part of the parameter while matching.CONVERT (DATE, #PEndDate) OR CONVERT(varchar,#PEndDate,103)
3) Get Date Part only from DateTime using DateTime functions
ATEADD(dd, 0,
DATEDIFF(dd, 0, #PEndDate))
4) Get Date Part only from DateTime using FLOOR and CAST functions
CAST( -- Convert the integer to DATE
FLOOR(-- Get largest Integer less than or equal to the decimal value
CAST(GETDATE() AS DECIMAL(12, 5)) -- Convert DATETIME to DECIMAL)
AS DATETIME) 'Date Part Only'
5) Get Date Part only from DateTime using DATEPART and CONVERT functions
CONVERT(VARCHAR(4),DATEPART(YEAR, #GETDATE))
+ '/'+ CONVERT(VARCHAR(2),DATEPART(MONTH, #GETDATE))
+ '/' + CONVERT(VARCHAR(2),DATEPART(DAY, #GETDATE))
'Date Part Only'
Use whichever method suits you and you find fancy.
UPDATE
As you mentioned you need to get the time part to 00:00 with date so you can try as,
SELECT CAST( convert(varchar(10),GETDATE(),112) AS DATETIME)
--This will give you 2015-02-27 00:00:00.000
SELECT DATEADD(ms,-3, DATEADD(day, DATEDIFF(day,0,GETDATE())+1,0))
--This will give you end of days time 2015-02-27 23:59:59.997
SELECT CONVERT(nvarchar,getdate(),103) + ' 12:59:59 PM'
--This will give you custom time 27/02/2015 12:59:59 PM
Hi all I have the following Query made using the Query Builder in Visual Studio.
SELECT Schd_ID, Schd_Date, Schd_Avaliable, Schd_Nights, Schd_Price, Accom_ID
FROM Schedule
WHERE (Schd_Avaliable = 'Yes') AND (Accom_ID = Accom_ID)
I want to add another WHERE statement which adds where Schd_Date is after todays date, any ideas?
Assuming SQL Server, the GETDATE() function returns the date and time the statement was run at:
WHERE Schd_Date > GETDATE()
Use the following for finding dates greater than the current date at midnight:
WHERE Schd_Date > DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
However, CURRENT_TIMESTAMP is the ANSI means of getting the current date and time in a database. Beyond that, date functionality is not consistent between databases so you'd have to tell us what you are dealing with for better answers.
If this is SQL Server you could use the GETDATE() function to return the current date and compare against it:
SELECT
Schd_ID, Schd_Date, Schd_Avaliable, Schd_Nights, Schd_Price, Accom_ID
FROM
Schedule
WHERE
(Schd_Avaliable = 'Yes')
AND
(Accom_ID = Accom_ID)
AND
(Schd_Date > GETDATE())
SELECT Schd_ID, Schd_Date, Schd_Avaliable, Schd_Nights, Schd_Price, Accom_ID
FROM Schedule
WHERE (Schd_Avaliable = 'Yes') AND (Accom_ID = Accom_ID) AND (GETDATE() < Schd_Date)
This should work
I guess this expression can be used as a date representing the current date on the format yyyy-mm-dd (without the hours,minutes and seconds).
(Datepart('yyyy',getdate())+ '-' +Datepart('m',getdate())+ '-' + Datepart('d',getdate()))
therefore
SELECT Schd_ID, Schd_Date, Schd_Avaliable, Schd_Nights, Schd_Price, Accom_ID
FROM Schedule
WHERE (Schd_Avaliable = 'Yes') AND (Accom_ID = Accom_ID) AND
(Schd_Date >= (Datepart('yyyy',getdate())+ '-' +
Datepart('m',getdate())+ '-' +
Datepart('d',getdate())))
I have a query that searches by date. the dates in the database include the time. How do I search on just the date only.
select *
from weblogs.dbo.vwlogs
where Log_time between #BeginDate and #EndDAte
and (client_user=#UserName or #UserName Is null)
order by Log_time desc
cmd.Parameters.AddWithValue("#BeginDate", txtBeginDate.Text);
cmd.Parameters.AddWithValue("#EndDAte", txtEndDate.Text);
Leave your sql mostly as is and just fix your parameters:
cmd.Parameters.Add("#BeginDate", SqlDbType.DateTime).Value =
DateTime.Parse(txtBeginDate.Text).Date;
cmd.Parameters.Add("#EndDAte", SqlDbType.DateTime).Value =
// add one to make search inclusive
DateTime.Parse(txtEndDate.Text).Date.AddDays(1);
You also want to check to make sure your textboxes are valid datetimes first, but you should get the idea.
The only caveat here is that due to a quirk with the BETWEEN operator it will match the first instant of the next day. So, to fix that we write the query like this:
SELECT *
FROM vwlogs
WHERE Log_time >= #BeginDate AND Log_Time < #EndDate
AND (client_user=#UserName OR #UserName IS NULL)
ORDER BY Log_time DESC
Pay special attention to the comparision operators around the date.
The first thing to do is to remove the times from the dates. If you want to do this in the sql server code you can use something like the code below. I have this as a function on all the databases I work on
cast(floor(cast(#fromdate as float)) as datetime)
The next thing to worry about is the where criteria. You need to make sure you select everything from the start of the from date to the end of the to date. You also need to make sure queries for one day will work which you can do with a date add like this
Where LogTime >= #fromdate and LogTime < DateAdd(dd, 1, #todate)
In SQL round the start and end date to Whole Dates and use >= #BeginDate and very specifically < #EndDAte. The "rounding" process is not very elegant I'm afraid
e.g.
SELECT #BeginDate = DATEADD(Day, DATEDIFF(Day, 0, #BeginDate), 0),
#EndDAte = DATEADD(Day, DATEDIFF(Day, 0, #EndDAte) + 1, 0)
select *
from weblogs.dbo.vwlogs
where Log_time >= #BeginDate
and Log_time < #EndDAte
and (#UserName Is null OR client_user=#UserName)
order by Log_time desc
Note that I've moved "#UserName Is null" first, as there is some evidence that this test will easily pass/fail, and will cause the second more CPU intensive test (client_user=#UserName) to be ignored if the first test is TRUE (may be TommyRot of course ...)
Also, for best performance, you should explicitly name all the columns you need, and not use "SELECT *" (but that may just have been for the purpose of this question)
If you want to change the sql instead,
TRUNC(Log_Time) will reduce every datetime to to that date at midnight.
Make sure that you build your index on the column as TRUNC(Log_TIME) so it's usable.
Another gotcha - truncating your end date will NOT include that date! Consider:
WHERE Log_Time >= #BeginDate AND Log_Time < #EndDate
If #EndDate is truncated it will be midnight and not match anything on that day. You'll need to add a day!
Clean up the dates by adding the following line before your query...
select
#begindate=dateadd(day,datediff(day,0,#begindate),0),
#enddate=dateadd(ms,-3,dateadd(day,datediff(day,0,#enddate),1))
This will floor your begin date to the lowest possible time (00:00:00.000), and ceiling your end date to the highest possible (23:59:59.997). You can then keep your BETWEEN query exactly as it was written.
select *
from weblogs.dbo.vwlogs
where Log_time between #BeginDate and #EndDAte
and (client_user=#UserName or #UserName Is null)
order by Log_time desc
Hope this helps.