SQL Server Determining Hard Coded Date as Larger When It's Not? - sql-server

An old employee left a massive query behind that I've been debugging and it appears that the issue has come down to SQL Server itself determining a comparison differently than what I would have expected.
I have a table with a column col1 containing the value 20191215 as a datetime.
The part in question is similar to the following:
select case when col1 > '01/01/2020' then 1 else 0 end
This statement is returning 1, suggesting that '12/15/2019' is larger than '01/01/2020'.
I do not need assistance correcting the query, as I have already made changes to do so other than using the comparison the previous employee was using, I am simply curious as to why SQL Server would evaluate this as I have described.
I understand that this is not the typically way SQL Server would store dates as well, would the issue simply be the formatting of the dates?
Current SQL Server version is: SQL Server 2014 SP3 CU3.
SQL Fiddle link that shows the same results
Please note that the link does not contain an exact replica of my case
Edit: Included additional info relevant to actual query.

It is a string comparison not a date comparison:
select case when '12/15/2019' > '01/01/2020' then 1 else 0 end
vs
select case when CAST('12/15/2019' AS DATE) > CAST('01/01/2020' AS DATE) then 1 else 0 end
db<>fiddle demo
I am simply curious as to why SQL Server would evaluate this as I have described.
'12/15/2019' it is a string literal, SQL Server does not know you want to treat a date unless you explicitly express your intention.
I have a table with a column col1 containing the value 20191216
If you are comparing with a column then the data type of column matters and data type precedence rules

Related

Is there a way to extract individual values from a varchar column using SQL Server 2016?

I am trying to extract individual dates from a varchar column in a SQL Server 2016 tablet that are stored comma separated and am not sure how to proceed. The data is setup like this:
article Consolidation_Order_Cut_Off_Final_Allocation
------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
011040 01/13/2021,03/10/2021
019099 01/13/2021,01/27/2021,02/24/2021,03/24/2021,04/28/2021,05/26/2021,06/23/2021,07/28/2021
019310 01/27/2021,02/03/2021,03/10/2021,04/14/2021,05/12/2021,06/09/2021,07/14/2021,08/11/2021
059611 01/13/2021
Ideally - I would have each date split out into a new row. I have seen a few similar questions that use very complex functions but those seem to be for SQL Server 2008. I have also found the new function STRING_SPLIT but that would seem to be table valued and thus have to come in the FROM. One thought I had was to declare a variable to hold this column and then use something like select * FROM string_split(#dates,','); however since there is more than one value in that list that returns an error. I am very new to the 2016 version of SQL Server and curious if anyone has ran into a way to solve this.
String_Split() is a table valued function, so you can call it with a CROSS APPLY
Example or dbFiddle
Select A.article
,B.Value
From YourTable A
Cross Apply string_split(Consolidation_Order_Cut_Off_Final_Allocation,',') B

How to convert rows of data into a single row through informatica/SQL Server

How to convert diagonal rows into single row in SQL Server 2014 for a particular ID field. Any help would be greatly appreciated
Please review.
My source is SQL Server 2014
Note:
I don't have write access to DB so will not be able to create functions etc.
I have option to get the desired o/p either by taking the source[given below] in Informatica from SQL Server - which is in turn result of a query and achieve the required o/p by applying some transformation or write logic in SQL server -2014. So in short either i can perform logic using Informatica or through SQL Server in the initial level itself to get the desired o/p.
I have several other joins and columns being pulled from different tables along with the below fields
Please review
Regarding Input:
The ID field will be constant, but POS field will be different for a particular ID
There can be 1 to 10 such occurrences of POS field [POS field can have values from 1 -10].DESC1 value from POS =1 will go to DESC1, value of POS 2 will go to desc2 and so on.
Right now I have given only 8 occurrences,but actually there are 10
INPUT:
ID|POS|DESC1|desc2|desc3|desc4|desc5|desc6|desc7|desc8|
1|1|ItemA|null|null|null|null|null|null|null
1|2|null|ItemB|null|null|null|null|null|null
1|3|null|null|Item C|null|null|null|null|null
1|4|null|null|null|ItemD|null|null|null|null
1|5|null|null|null|null|ItemE|null|null|null
1|6|null|null|null|null|null|value-random|null|null
1|7|null|null|null|null|null|null|Check!A|null
1|8|null|null|null|null|null|null|null|123456
OUTPUT:
ID|DESC1|desc2|desc3|desc4|desc5|Desc6|desc7|Desc8
1|ItemA|ItemB|Item C|ItemD|ItemE|value-random|Check!A|123456
This is simplified because I don't know what your current query looks like but you could use MAX() and GROUP BY id.
DEMO
SELECT
ID,
MAX(desc1) AS [desc1],
MAX(desc2) AS [desc2],
MAX(desc3) AS [desc3],
MAX(desc4) AS [desc4],
MAX(desc5) AS [desc5],
MAX(desc6) AS [desc6],
MAX(desc7) AS [desc7],
MAX(desc8) AS [desc8]
FROM dbo.YourTable
GROUP BY ID

Non deterministic data type in SQL Server

I was creating a table in my SQL Server database when a specific attribute Deterministic of the database columns caught my attention. Please see the screenshot below:
I am already aware of Deterministic and Non-Deterministic SQL Server functions but I want to know that does it apply even to data data types in SQL Server in any way?
The reason why I'm asking is that I literally scanned through all the data types available in SQl Server v2008 and v2012 but the value of Deterministic field showed Yes for all of them. It didn't show No for any single data type.
So my question is that is it a proper attribute of any data type in SQL Server which still affects the way values are stored in the column or it is just a legacy from the past, may be from SQL Server 2000 or SQL Server 2005 where there used to be some data types which were non-deterministic in nature. Any information will be very useful to understand this characteristic of data types in SQL Server. Do we have any data type in SQL Server as of today which is non-deterministic in nature?
Since I didn't see No for any of the data types I got more got confused. I also googled a lot but every search takes me to Deterministic and Non-Deterministic SQL Server functions like the one below and nobody talks about Non-deterministic characteristic relating to SQL Server data types.
https://technet.microsoft.com/en-us/library/ms178091(v=sql.110).aspx
If you read this MSDN documentation carefully, you'll find:
IsDeterministic - Column is deterministic. This property applies only
to computed columns and view columns.
It applies to columns (computed, view) derived from another columns with non-deterministic functions involved.
Examples:
CREATE TABLE Deterministic
(
ID int,
Calculated AS SYSDATETIME()
)
SELECT COLUMNPROPERTY(OBJECT_ID('Deterministic'), 'Calculated', 'IsDeterministic') IsDeterministic
--Returns 0
If you create view on this table as follows and execute following query
CREATE VIEW vDeterministic AS
SELECT ID, Calculated, DATEADD(D, 1, Calculated) Tomorrow
FROM Deterministic
GO
SELECT 'Calculated' ColumnName,
COLUMNPROPERTY(OBJECT_ID('vDeterministic'), 'Calculated', 'IsDeterministic') IsDeterministic
UNION ALL
SELECT 'Tomorrow',
COLUMNPROPERTY(OBJECT_ID('vDeterministic'), 'Tomorrow', 'IsDeterministic')
You also receive non deterministic columns
ColumnName IsDeterministic
---------- ---------------
Calculated 0
Tomorrow 0

Conversion Failed Varchar to Date with TOP and WHERE

I've got a MSSQL 2012 server that holds olders databases (day by day) of my ERP. Simple JOB restores a newest databases from my backup server and removes the oldest one's. It was working fine for few months, but a week ago it started to fail. One of the queries returns: 'Conversion failed when converting date and/or time from character string.'
All database have the same schema for a name 'DATABASE_date' ex.: 'DATABASE_20150224'.
This is the query:
SELECT TOP 1 name
from sys.databases
where name like 'DataBaseName_%'
order by CAST(right(name,8) as DATE)
IF i remove 'TOP 1' it works fine.
SELECT name
from sys.databases
where name like 'DataBaseName_%'
order by CAST(right(name,8) as DATE)
It seems like MSSQL check's all databases on this server (2 new databases of a different app). But why? There's a 'WHERE' cluase and simple select works just fine.
SQL is a declarative language. A database is free to first order the rows and then filter them, or the other way around.
You are relaying on a where clause to filter out rows that would cause an exception in your string manipulation expression. But SQL Server can run the where after the order by.
One approach is bullet-proofing the order by:
order by
case
when name not like 'DataBaseName_%' then name
else CAST(right(name,8) as DATE)
end
Note that even this isn't 100% guaranteed to work. SQL Server could legally evaluate both sides of the case and throw away the second one.

How to fix "domain error" in SQL Server 2005 when using LOG() function to get product of set

I have a inline select statement to calculate the product of the set of values.
Since SQL Server 2005 doesn't have a built in Product aggregate function, I am using LOG/EXP to get it.
My select statement is:
(select exp(sum(log(value))) from table where value > 0)
Unfortunately I keep getting the following error:
Msg 3623, Level 16, State 1, Line 1
A domain error occurred.
I've ensured that none of the values are zero or negative so I'm not really sure why this error is occurring. Does anyone have any ideas?
One of the features of the query planner introduced in SQL 2005 is that, in some circumstances where the table statistics indicate it will be more efficient, the WHERE clause of a statement will be processed after the SELECT clause.
(I can't find the Books On-Line reference for this right now).
I suspect this is what is happening here. You either need to exclude the rows where value = 0 before carrying out the calculation - the most reliable way being to store the rows you need in a temporary (#) table - or to modify your query to handle zero internally:
SELECT EXP(SUM(LOG(ISNULL(NULLIF(VALUE,0),1)))) AS result
FROM [table]
The NULLIF\ISNULL pair I have added to your query substitutes 1 for 0 - I think this will work, but you will need to test it on your data.

Resources