SQL Select Query on Date/Time column strange behavior - sql

I am having an odd issue with a select statement in SQL Server Express, hopefully someone can shed some light on why I'm experiencing this behavior as well as the right way to do it.
When I run this query it returns exactly what I would expect:
SELECT
Action, TimeOccurred, UserName, IPv4From, ShareName,
FullFilePath, NewPathName, FromServer
FROM
File_System_Profiles
WHERE
Action LIKE '%create%'
AND (TimeOccurred >= '04/27/2017')
All those entries from 4/27 and anything after that.
When I run this query it returns 0 results which is extremely odd since there are entries for 4/27 in the previous query's results:
SELECT
Action, TimeOccurred, UserName, IPv4From, ShareName,
FullFilePath, NewPathName, FromServer
FROM
File_System_Profiles
WHERE
Action LIKE '%create%'
AND (TimeOccurred = '04/27/2017')
All I removed was the > between the = and the date and I get no results. I can clearly see when I run the first query that there are results where 04/27/2017 is the date that something occurred. If the first query didn't work I would assume there was a problem with my date format of MM/DD/YYYY and what is actually in the column YYYY-MM-DD HH:MM:SS but since the first one works it seems logical that the second one should.

It is a problem of the date format. As you mentioned, you are using Date format as "YYYY-MM-DD HH:MM:SS" so you should know that the value "04/27/2017" will be taken as "04/27/2017 00:00:00" when used in the comparison.
I assume that you have no record where the value in date field is "04/27/2017 00:00:00" and that is why when you use = operator, it does not match any record. However, the operator >= picks the records where hour:minute:second part of the date exist. As an example "04/27/2017 01:10:00" is greater than "04/27/2017 00:00:00" and therefore the > operator fetches those records.
Hope it helps.

First, always use ISO standard formats for comparison. Your code should look more like this:
where Action LIKE '%create%' AND
TimeOccurred = '2017-04-27'
Nauman explained the problem, which is the time component on TimeOccurred. You can solve this in various ways. One method is to convert to date. Something like this:
where Action LIKE '%create%' AND
cast(TimeOccurred as date) = '2017-04-27'
Depending on the database, the cast() might be replaced by trunc() or date_trunc() or something else.
However, I prefer this version:
where Action LIKE '%create%' AND
TimeOccurred >= '2017-04-27' AND
TimeOccurred < '2017-04-28'
It gets to the heart of the problem. And -- better yet -- SQL optimizers can make use of an index.

Related

SQL Count Where on a specific date... but the result is 0

Hi it is NOT my first time the i use this query:
SELECT COUNT(*) from dbo.SchDetail WHERE dbSchDate = '08-06-2020'
Query is working but he counts everytime 0.
But if i do a between "08-06-2020" and "07-06-2020".
I got the right result.
For mysql both query working fine.
But not on MSSQL.
I dont know what I do wrong.
Thanks for help
You are getting 0 because the WHERE clause filters out all rows. There are multiple reasons; for instance:
The table could be empty.
dbSchDate could be a datetime with a time component.
The constant may not be interpreted correctly as a date/time.
No values in the table might match.
I would suggest a proper date format, in YYYYMMDD format:
WHERE dbSchDate = '20200806'
You can also use:
WHERE dbSchDate >= '20200806'
dbSchDate < '20200807'
This version works even if there is a time component, as does:
WHERE CONVERT(DATE, dbSchDate) = '20200806'

use of trunc date in sql

can anyone explain me the working of trunc(date) function in oracle.
my query is as below.
select trunc(tran_date) from tablename;
i have not passed any format type.
If i compare the date present in table without having trunc(date) it will not give any output.
and if compare date table with trunc(date) it will give me proper ouptut.
please explain how it is working.
and is there any replacement for trunc function as it is taking too much time.
trunc(tran_date) returns the date portion of the date column with no time component (which is midnight at the start of the day).
Despite its name, the date data type in Oracle includes the time. This is even more confusing because you sometimes do not see the time in the result set (depending on how you access the data).
The dates that you are comparing to have no time component. So, the comparison works with trunc(). But the time component on tran_date prevents the comparison from working without trunc().

SQL - How to search WHERE but ignore first two characters

I need to perform a date search but the data is a String with the format
'dd/mm/yyyy'
I want to search only for 'mm/yyyy'
For example I want all records that have '07/2014' regardless of what day?
I'm sure its something simple just can't figure it out
EDIT:
It looks like the format is MM/DD/YYY
Looks like I got this sorted just used:
RIGHT(BookedDate,5) = '/2014'
AND LEFT (BookedDate,2) = '7/'
Thanks All :)
If your string is in the format of dd/mm/yyyy always, as in 01/09/2014 you could use right:
declare #val as varchar(10)
Set #val='1/2/2014'
RIGHT(#val,7)
if you are not sure of the format but know that there is a / you could search for it:
declare #val as varchar(10)
Set #val='1/2/2014'
select right(#val,len(#val)-patindex('%/%',#val))
myfield like '%/07/2014'
Beware, since the wildcard (%) is put at the beginning of the query no indexes (if they exist) will be used. This will always be a full table scan.
If you store your date values in character based column, than jyparask's answer is good enough, but if you store it in date/time based column, then use date/time functions or intervals:
WHERE
myDateColumn >= '01/07/2014'
AND myDateColumn < '01/08/2014'
The above WHERE condition means: all values in July, 2014.
This will ensure that, because its a string, if the value is longer than expected the first three characters will always be removed.
SELECT RIGHT(field, LEN(field)-3) FROM database
This feels like a very bad idea. Most likely there is a ton of optimizations that could be done automatically for your queries by the database if you used Date instead of the String.
This is certainly going to be some kind of bottleneck if your database grows, it would have to ask and parse every single row to find out if it matches your request.

Unknown SQL coding issue in Oracle SQL Developer

I'm writing an SQL statment that is supposed to do a count based on a date range. But, for some reason no data is being returned. Before I try and filter the count with my date range, everything works fine. Here is that code.
SELECT
CR.GCR_RFP_ID
,S.RFP_RECEIVED_DT
,CR.GCR_RECEIVED_DT
,CT.GCT_LOB_IND
FROM ADM.GROUP_CHANGE_TASK_FACT CT
JOIN ADM.B_GROUP_CHANGE_REQUEST_DIM CR
ON CR.GROUP_CHANGE_REQUEST_KEY = CT.GROUP_CHANGE_REQUEST_KEY
JOIN ADM.B_RFP_WC_COVERAGE_DIM S
ON S. RFP_ID = CR.GCR_RFP_ID
WHERE CT.GCT_LOB_IND = 'WC'
AND CR.GCR_CHANGE_TYPE_ID IN ('10','20','30','50','60','70','80','90','100','110',
'120','130','140', '150','160','170','180','190','200',
'210','220','230','240','260','270','280','300','310',
'320','330','340','350','360','370','371','372')
AND S.RFP_AUDIT_IND = 'N'
AND S.RFP_TYPE_IND = 'A'
The date field I'm using is called CR.GCR_RECIEVED_DT. This is a new field a in the db and all the records are 01-JAN-00. But I'm still doing the count just to make sure I can grab the data. Now, I added this line:
AND CR.GCR_RECEIVED_DT LIKE '01-JAN-00'
just as a random test thing. I know all the dates are the same. And it works fine, no issues. So I remove that line and replace it with this:
AND CR.GCR_RECEIVED_DT BETWEEN '31-DEC-99' AND '02-JAN-00'
I used this small range to keep it simple. But even though 01-JAN-00 deffinetly falls between those two dates, no data is returned. I have no idea why this is happening. I even tried this line to:
AND CR.GCR_RECEIVED_DT = '01-JAN-00'
and I still don't get data returned. It only seems to work with LIKE. I have checked and the field is a date type. Any help wold be much appreciated.
If your NLS_DATE_FORMAT is set to DD-MON-YY then the apparent discrepancy between the first two results can be explained.
When you use LIKE it implicitly converts the date value on the left-hand side to a string for the comparison, using the default format model, and then compares that to the fixed string; and '01-JAN-00' is like '01-JAN-00'. You're effectively doing:
AND TO_CHAR(CR.GCR_RECEIVED_DT, 'DD-MON-YY') LIKE '01-JAN-00'
Using LIKE to compare dates doesn't really make any sense though. When you use BETWEEN, though, the left-hand side is being left as a date, so you're effectively doing:
AND CR.GCR_RECEIVED_DT BETWEEN TO_DATE('31-DEC-99', 'DD-MON-YY')
AND TO_DATE('02-JAN-00', 'DD-MON-YY')
... and TO_DATE('31-DEC-99', 'DD-MON-YY') is December 31st 2099, not 1999. BETWEEN only works when the first value is lower than the second (from the docs, 'If expr3 < expr2, then the interval is empty'). So you're looking for values bwteen 2099 and 2000, and that will always be empty. If your date model was DD-MON-RR, from the NLS parameter or explicitly via TO_DATE, then it would be looking for values between 1999 and 2000, and would find your records.
Your third result is a little more speculative but suggests that the values in your GCR_RECEIVED_DT field have a time component, or are not in the century you think. This is similar to the LIKE version, except this time the fixed string is being converted to a date, rather than the date being converted to a string; effectively:
AND CR.GCR_RECEIVED_DT = TO_DATE('01-JAN-00', 'DD-MON-YY')
If they were at midnight on 2000-01-01 this would work. Because it doesn't that suggests they are either some time after midnight, or maybe more likely - since you're using a 'magic' date in your existing records - they are another date entirely, quite possibly 1900-01-01.
Here are SQL Fiddles for just past midnight and 1900.
If the field will eventually have a time component for new records you might want to structure the condition like this, and use date literals to be a bit clearer (IMO):
AND CR.GCR_RECEIVED_DT >= DATE '2000-01-01'
AND CR.GCR_RECEIVED_DT < DATE '2000-01-02'
That will find any records at any time on 2000-01-01, and can use an index on that column if one is available. BETWEEN is inclusive, so using BETWEEN DATE '2000-01-01' AND '2000-01-02' would include any records that are exactly at midnight on the later date, which you probably don't want.
Whatever you end up doing, avoid relying on implicit conversions using NLS_DATE_FORMAT as one day it might not be set to what you expect, causing potentially data-corrupting or hard to find bugs; and specify the full four-digit year in the model if you can to avoid ambiguity.
try something like this:
WHERE TRUNC(CR.GCR_RECEIVED_DT) = TO_DATE('01-JAN-00','DD-Mon-YY')
TRUNC without parameter removes hours, minutes and seconds from a DATE.

XCODE - SQL Dates

I am trying to update my SQL DB when the the date has expired (i.e is less than now)
I have this lovely bit of SQL code
Update Notifications
SET Active = 'N'
where CAST(SetDate AS DATE) <= CAST('2012-08-23 11:19:00 +0000' AS DATE)
But it updates all the records (even if the date is not less than now)
I have also tried
Update Notifications
SET Active = 'N'
where CAST(SetDate AS DATE) < CAST('2012-08-23 11:19:00 +0000' AS DATE)
But this dosent affect any rows.
I guess I have something a little confused??
Any help???
Thanks
I cannot see anything odd about the code, except for this line:
CAST('2012-08-23 11:19:00 +0000' AS DATE)
If you are using CAST() to change it to the date, then there is no need to pass in the time portion of the value.
You did not provide the full table schema but one thing to consider is using a bit field for the Y/N values.
Here is a SQL Fiddle with the code working
Update Notifications
SET Active = 'N'
where CAST(SetDate AS DATE) <= CAST('2012-08-23' AS DATE)
One thing you have confused is types in SQL. I don't know what database you are using, but it probably has types for boolean (or int) and date. Storing booleans and dates as strings is very inefficient. For example, even if your example did work it would have to scan the entire database and cast each value in order to compare it.
The clue to the error is the < vs <=. This hints at the values being equal. If the cast fails on both sides, and returns the default value of zero, then then will be equal.
You should change your schema to use the correct types, then your query will work.