SQL replace using SELECT and invalid column - sql

I have a simple table where the date column answer_6 (formatted as varchar(max) either has a valid date or string Now. I wanted to substitute the Now with the current date/time and then calculate the difference. Here is what I did:
select
CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END as x,
answer_6 from [tDataMult] where DATEDIFF(yy, GETDATE(), [x]) > 5
The system give me invalid column name 'x'. If I remove the DateDiff SELECT statement works fine.

You can't use aliases in the WHERE clause of the same level as it was defined as WHERE clause is evaluated before the SELECT clause. Try the following :
SELECT t.* FROM (<...>) t WHERE DATEDIFF(yy, GETDATE(), [t.x]) > 5
Instead <...> put your query without WHERE clause.

You can't refer to an alias you've just created in a WHERE clause. The easiest way to fix it would just be to turn your original query into a subquery:
SELECT *
FROM
(
select
CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END as x,
answer_6 from [tDataMult]
) AS qry
WHERE DATEDIFF(yy, GETDATE(), [x]) > 5
Or you could replicate the expression in your WHERE clause:
select
CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END as x,
answer_6 from [tDataMult]
WHERE DATEDIFF(yy, GETDATE(),
(CASE [answer_6]
WHEN 'Now' THEN CONVERT(varchar, GETDATE())
ELSE answer_6
END)
) > 5

Column X does not exist in tDataMult table because it is an alias.
Replace it with answer_6 in DateDiff function.
However, one of the possible value of answer_6 column is varchar format ('Now').
You need to have valid data format to use DATEDIFF function properly. (for example: 'yyyy-mm-dd').

Related

Subtract substring days from date

I'm trying to come up with a Select statement that would return the DATE column minus the number of days in the DAYS column.
This is the query I tried:
SELECT
DATEADD(DAY, -+(REPLACE(ISNULL(DAYS,0), 'DAYS', '')), DATE)
FROM
T
It throws an error
Operand data type varchar is invalid for minus operator
dateadd(day, -1*convert(int, coalesce(replace([DAYS], ' days', ''),'0')), [DATE])
Something like
DECLARE
#Days VARCHAR(25) = '23 DAYS',
#Date DATE = '2018-10-23';
SELECT DATEADD(Day, - CAST(REPLACE(#Days , 'DAYS', '') AS INT), #Date )
If you are using SQL Server 2012+
SELECT DATEADD(Day, - ISNULL(TRY_CAST(REPLACE(#Days , 'DAYS', '') AS INT), 0), #Date )
I think you need to get the number, cast it to integer as negative and use dateadd like below:
SELECT dateadd(DAY,cast('-'+substring([DAYS], 1,charindex(' ',[DAYS])) as int),[DATE])
FROM T
You can use this:
Use CHARINDEX to get the number of days and convert to int
and then minus it from date column
select DATEADD(DAY,-CAST(SUBSTRING(days,1,CHARINDEX(' ',days)) AS INT),DATE),* from #table
The DATEADD function expects an integer for its second parameter argument.
By REPLACING 'DAYS' with an empty string, you are still left with a varchar containing a number and the blank space that was between that number and the word "DAYS".
RTRIM this result and CAST it as an Integer, and you should be good to go.
Oh, and you also need to put ,DATE inside the DATEADD()'s parenthesis.

Putting a word in the select statement

I want to put the word "days" after the value, but the sql server is reacting that it cannot be converted. How can I also not select the negative integers difference.
SELECT PONo, PODeliveryDate, DATEDIFF(DAY, GETDATE(), PODeliveryDate) AS DayDiff
FROM PurchaseOrder
where POStatus='Complete' OR POStatus='Partially Completed' OR POStatus='Approved'
ORDER BY ABS( DATEDIFF( DAY, GETDATE(), PODeliveryDate ))
It gives me the difference of dates, but I cannot put the word days beside it.
I want it to look like 5 days not just 5
Try to convert the int value from DATEDIFF() to varchar and add your word
SELECT PONo
, PODeliveryDate
, CAST(DATEDIFF(DAY, GETDATE(), PODeliveryDate) as varchar(10)) + ' days' AS DayDiff
FROM PurchaseOrder
WHERE POStatus='Complete'
OR POStatus='Partially Completed'
OR POStatus='Approved'
ORDER BY ABS( DATEDIFF( DAY, GETDATE(), PODeliveryDate ))
Convert this first DATEDIFF(DAY, GETDATE(), PODeliveryDate) into VARCHAR before you concatinate.
CONVERT(VARCHAR(50), DATEDIFF(DAY, GETDATE(), PODeliveryDate)) + 'days'
In sqlserver 2012, you can use CONCAT.
To only get the positive days, you can cast getdate as date and compare with that in the WHERE statement. Then you dont need to order by ABS datediff.
The WHERE clause is easier to read and maintain by using IN instead of OR, it also makes is easier to maintain.
SELECT
CONCAT(DATEDIFF(DAY, GETDATE(), PODeliveryDate), ' days') AS DayDiff
FROM
PurchaseOrder
WHERE
POStatus in ('Complete','Partially Completed','Approved')
AND CAST(GETDATE() as date) <= PODeliveryDate
ORDER BY
PODeliveryDate
Can you try like as follow:
select CONVERT(varchar(10), GETDATE()) + ' Days'
You need to convert or cast into varchar before concate

converting date format to eliminate time stamp

I have a table where the date and time stamp are logged together and I want to only show the date in a 10 character output. Also I want to return as blank some dates in the field that are 01/01/1800.
The current table format is 2013-06-28 00:00:00:000
I just want the date. I was using RTRIM function but it keeps erroring out.
Thanking you in advance
Try this:
SELECT CASE CONVERT(DATE, #MyValue) WHEN '01/01/1800' THEN NULL ELSE CONVERT(DATE, #MyValue) END
Or if you prefer:
DECLARE #DateOnlyValue DATE
SET #DateOnlyValue = CONVERT(DATE, #MyValue)
SELECT CASE #DateOnlyValue WHEN '01/01/1800' THEN NULL ELSE #DateOnlyValue END
The latter is just DRYer.
You can just do:
select (case when datecol > '1800-01-01' then convert(varchar(10), datecol, 121) end)
This will convert the value to a string of the form YYYY-MM-DD.
This uses NULL for "blank". If you want an empty string:
select (case when datecol > '1800-01-01'
then convert(varchar(10), datecol, 121)
else ''
end)
This also assumes that the values with '1800-01-01' don't have a time component. That seems reasonable for a default extreme value.

SQL Server: Use different date format in Select when selected date equals current date

I have a table with a column "modTime" formatted as datetime.
To fetch dates from this column I use the following line in my Select which returns a date in the format DD MMM YYYY:
CONVERT(VARCHAR(11), G.modTime, 106) AS modTime
Is there a way that I can return the date in a different format (like the following) when it matches the current date and only otherwise use the above format ? This returns the date as Today at hh:mm.
('Today at ' + CONVERT(VARCHAR(5), G.modTime, 108)) AS modTime
Both ways work when I use them separately but I couldn't find a way to combine them using CASE etc.
You can try this:
select iif(G.modTime=getdate(),('Today at ' + CONVERT(VARCHAR(5), G.modTime, 108)),CONVERT(VARCHAR(11),G.modTime, 106) ) from <table name>
Please note that IIF works only with SQL Server 2012 or later.
http://msdn.microsoft.com/en-IN/library/hh213574.aspx
For older versions, this post might help you:
SQL Server 2008 IIF statement does not seem enabled
you will not match to getdate() using equals, and you need to set getdate()'s time to midnight
select
case when G.modTime >= dateadd(day, datediff(day,0, getdate() ), 0)
then ('Today at ' + CONVERT(VARCHAR(5), G.modTime, 108))
else
CONVERT(VARCHAR(11), G.modTime, 106)
end AS modTime
from G
Above I have used: dateadd(day, datediff(day,0, getdate() )
Instead you could use: cast(getdate() as date)
both, have the effect of giving you "today" at 00:00:00

"CASE" statement within "WHERE" clause in SQL Server 2012

i have a select statement like this
select x, y , z from table a
where CAST( CAST(DATEColumn AS VARCHAR) AS DATE) between
case when a.columnx = '1900-01-01' then CAST( CAST(DATEColumn AS VARCHAR) AS DATE) else c.columnx end
and cast( c.CustomerShipToRecTrmDt as date)
why does this case statement does not work
whereas the case statement works if i hardcode the dates?
What are you casting a date columns to varchar and then back to a date? I think this does what you want:
select x, y , z
rom table a
where DATEColumn between
(case when a.columnx = '1900-01-01' then DATEColumn else cast(c.columnx as date) end and
cast( c.CustomerShipToRecTrmDt as date)
You can eliminate the case statement from the where clause by doing:
where DATEColumn >= cast(c.columnx as date) and DateColumns <= cast( c.CustomerShipToRecTrmDt as date)
The comparison to 1900-01-01 doesn't affect the >= part, unless you are working with dates before 1900 (I'm guessing this is unlikely).
Also, whenever casting values to varchar(), always include the length (as in varchar(255)).