XCODE - SQL Dates - sql

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.

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'

Sql Server Table date query showing incorrect result

I have a Sql server table which contains below Date values(4th october)
Now Below query is not showing any result
select
*
from [dbo].[TB_AUDIT] TBA
where TBA.ActionDate >= '10/01/2018' and TBA.ActionDate <= '10/04/2018' which is not correct.
But If I write
select
*
from [dbo].[TB_AUDIT] TBA
where TBA.ActionDate >= '10/01/2018' and TBA.ActionDate <= '10/05/2018' it is returning me all results.
What I am doing wrong.
There are two problems with this query. The first, is that it's using a localized string. To me, it looks like it's asking for rows between January and April. The unambiguous date format is YYYYMMDD. YYYY-MM-DD by itself may not work in SQL server as it's still affected by the language. The ODBC date literal, {d'YYYY-MM-DD'} also works unambiguously.
Second, the date parameters have no time which defaults to 00:00. The stored dates though have a time element which means they are outside the search range, even if the date parameter was recognized.
The query should change to :
select
*
from [dbo].[TB_AUDIT] TBA
where
cast(TBA.ActionDate as date) between '20181001' and '20181004'
or
cast(TBA.ActionDate as date) between {d'2018-10-01'} and {d'2018-10-04'}
Normally, applying a function to a field prevents the server from using any indexes. SQL Server is smart enough though to convert this to a query that covers the entire date, essentially similar to
where
TBA.ActionDate >='2018:10:01T00:00' and TBA.ActionDate <'2018-10-05T00:00:00'
When you don't specify a time component for a DATETIME, SQL Server defaults it to midnight. So in your first query, you're asking for all results <='2018-10-04T00:00:00.000'. All of the data points in your table are greater than '2018-10-04T00:00:00.000', so nothing is returned.
You want
TBA.ActionDate >= '2018-10-01T00:00:00.000' and TBA.ActionDate < '2018-10-05T00:00:00.000'`
Use properly formatted dates!
select *
from [dbo].[TB_AUDIT] TBA
where TBA.ActionDate >= '2018-10-01' and TBA.ActionDate <= '2018-10-04'
YYYY-MM-DD isn't just a good idea. It is the ISO standard for date formats, recognized by most databases.
when you just filter by the date, it is with regard to the time as per the standard.

Using GETDATE() to pull from a table

My apologies in advance for the basic (and probably silly) question.
I'm doing a SELECT query where I'm joining several tables. I have a table that contains a numeric value associated with certain days. What I would like to have in my output is the numeric value attached to today, but I'm clueless as to how to make this happen. Obviously, I would have the same value for every record in my output and I'm fine with that.
Is this even possible? If so, what would an example of the code be?
The table from which I would like the numeric value simply has dates in one column ([Calendar_Day]) and integers in another column ([X_Value]).
Below, you can see the last three lines of my SELECT statement. This latest attempt yielded NULL.
,[EnterpriseDB].[pcc].[conditions].Internal
,GETDATE() AS Date_Today
,(SELECT [X_Value] FROM [Analytics].[WorkArea].[Days_Vals] WHERE [Calendar_Day] = GETDATE()) AS BizVal_Today
Just guessing:
[Calendar_Day] is of the type date. While getdate() returns a datetime. That means the DBMS upcasts [Calendar_Day] to a datetime with a time of 00:00:00.0 in order to be able to compare the operands. But getdate() includes the current time. So unless you're executing the query at exactly 00:00:00.0 the values won't match and the subquery returns null.
To fix that, downcast getdate().
... WHERE [Calendar_Day] = convert(date, getdate()) ...
If [Calendar_Day] is also a datetime but you don't want to compare the hour (, minute, second ...) portion of it, downcast it as well.
... WHERE convert(date, [Calendar_Day]) = convert(date, getdate()) ...
Might throw any indexes out of the window though, if there are some on [Calendar_Day]. You might want to consider changing the data type to date or using a persistent, indexed computed column and compare against that, if that leads to any performance issues.

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.

Date range comparison using varchar columns in Teradata

I've been tasked to take a calendar date range value from a form front-end and use it to, among other things, feed a query in a Teradata table that does not have a datetime column. Instead the date is aggregated from two varchar columns: one for year (CY = current year, LY = last year, LY-1, etc), and one for the date with format MonDD (like Jan13, Dec08, etc).
I'm using Coldfusion for the form and result page, so I have the ability to dynamically create the query, but I can't think of a good way to do it for all possible cases. Any ideas? Even year differences aside, I can't think of anything outside of a direct comparison on each day in the range with a potential ton of separate OR statements in the query. I'm light on SQL knowledge - maybe there's a better way to script it in the SQL itself using some sort of conversion on the two varchar columns to form an actual date range where date comparisons could then be made?
Here is some SQL that will take the VARCHAR date value and perform some basic manipulations on it to get you started:
SELECT CAST(CAST('Jan18'||TRIM(EXTRACT(YEAR FROM CURRENT_DATE)) AS CHAR(9)) AS DATE FORMAT 'MMMDDYYYY') AS BaseDate_
, CASE WHEN Col1 = 'CY'
THEN BaseDate_
WHEN Col1 = 'LY'
THEN ADD_MONTHS(BaseDate_, -12)
WHEN Col1 = 'LY-1'
THEN ADD_MONTHS(BaseDate_, -24)
ELSE BaseDate_
END AS DateModified_
FROM {MyDB}.{MyTable};
The EXTRACT() function allows you to take apart a DATE, TIME, or TIMESTAMP value.
You have you use TRIM() around the EXTRACT to get rid of the whitespace that is added converting the DATEPART to a CHAR data type. Teradata is funny with dates and often requires a double CAST() to get things sorted out.
The CASE statement simply takes the encoded values you suggested will be used and uses the ADD_MONTHS() function to manipulate the date. Dates are INTEGER in Teradata so you can also add INTEGER values to them to move the date by a whole day. Unlike Oracle, you can't add fractional values to manipulate the TIME portion of a TIMESTAMP. DATE != TIMESTAMP in Teradata.
Rob gave you an sql approach. Alternatively you can use ColdFusion to generate values for the columns you have. Something like this might work.
sampleDate = CreateDate(2010,4,12); // this simulates user input
if (year(sampleDate) is year(now())
col1Value = 'CY';
else if (year(now()) - year(sampleDate) is 1)
col1Value = 'LY'
else
col1Value = 'LY-' & DateDiff("yyyy", sampleDate, now());
col2Value = DateFormat(sampleDate, 'mmmdd');
Then you send col1Value and col2Value to your query as parameters.