How to convert IF function from Excel formula to TSQL? - sql-server

= if( _DataCell_ILF_Cred_ = "", "",
_DataCell_ILF_Lyr_Pick * _DataCell_ILF_Cred + _DataCell_Burn_Lyr_Pick_ * (1 - _DataCell_ILF_Cred_)
)
I want to convert this Excel IF Function into SQL code.

You can use CASE expression, or IIF() if you are working on SQL Server 2012+:
SELECT CASE WHEN _DataCell_ILF_Cred_ = ',' THEN
DoSomething
END
If _DataCell_ILF_Cred_ <> ',', it will return NULL, if you want to return another value instead of NULL, you need to add ELSE like:
SELECT CASE WHEN _DataCell_ILF_Cred_ = ',' THEN
DoSomething
ELSE
DoSomethingElse
END
However, your the last part of your if is not clear, you need to provide more information (as datatypes) to get better answer.

Literal translation (with some mock data) would be as follows:
select
1 as '_DataCell_ILF_Cred_',
2 as '_DataCell_ILF_Lyr_Pick',
3 as '_DataCell_Burn_Lyr_Pick'
into #test
select * from #test
declare #_DataCell_ILF_Cred_ decimal
if ((select [_DataCell_ILF_Cred_] from #test) <> '')
begin
select #_DataCell_ILF_Cred_ = [_DataCell_ILF_Lyr_Pick] * [_DataCell_ILF_Cred_]
+ [_DataCell_Burn_Lyr_Pick] * (1 -[_DataCell_ILF_Cred_])
from #test
select #_DataCell_ILF_Cred_ as [_DataCell_ILF_Cred_]
end
Do not hesitate to check IF...ELSE documentation:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql

Related

Use dynamic value in snowflake time travel sql

I want to use dynamic value in time travel sql of snowflake
select * from my_table at (timestamp => (select max(COMPLETION_DATE) from my_table_2):: timestamp)
When I ran something similar i got this error:
SQL compilation error: argument TIMESTAMP to function AT needs to be constant
I believe that a variable will work for this though:
set x = (select max(COMPLETION_DATE)::timestamp from my_table_2);
select * from my_table at (timestamp => $x);
Edit for a view
I don't think you can do this in a veiw, but you could do something like this probably with a UDF. See documentation here: https://docs.snowflake.net/manuals/sql-reference/udf-table-functions.html
Something like this:
create or replace function My_timetravel()
returns table (column1 varchar, column2 numeric(11, 2))
as
$$
set x = (select max(COMPLETION_DATE)::timestamp from my_table_2);
select column1, column2 from my_table at (timestamp => $x);
$$
;
select * from table(My_timetravel());
Time travel can only be specified with a constant, which makes i impossible to parametrize (currently).
The only way to do this is via a stored procedure, where you can supply a query as text.
I answered a similar question some days ago with this procedure:
CREATE OR REPLACE PROCEDURE TIME_TRAVEL(QUERY TEXT, DAYS FLOAT)
RETURNS VARIANT LANGUAGE JAVASCRIPT AS
$$
function run_query(query, offset) {
try {
var sqlText = query.replace('"at"', " AT(OFFSET => " + (offset + 0) + ") ");
return (snowflake.execute({sqlText: sqlText})).next();
}
catch(e) { return false }
}
var days, result = [];
for (days = 0; days < DAYS; days++)
if (run_query(QUERY, -days * 86400)) result.push(days);
return result;
$$;
CALL TIME_TRAVEL('SELECT * FROM TASK_HISTORY "at" WHERE QUERY_ID = ''019024ef-002e-8f71-0000-05e10030a782''', 7);
Session variable in Snowflake can work with query substitution and would help in the timestamp clause of your time travel query. Currently, this feature is not supported inside a UDF so you would declare the session variable and then use it with your UDF:
SET x = (SELECT current_timestamp());
CREATE OR REPLACE FUNCTION my_timetravel()
RETURNS TABLE (c1 int)
AS
$$
SELECT c1 FROM t1 AT (TIMESTAMP => $x)
$$
;
SELECT c1 FROM TABLE(my_timetravel());

SQL Server stored procedure query to return multiple columns

The following query returns 4 columns, but if I attempt to return the same from a stored procedure I get
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS
If I want to get the values returned in a comma delimited string how do I write it?
Working query
Declare #g geography = 'POINT(-1.2846387 52.686091)'
Select top 1
Round(Geocolumn.STDistance(#g)/1000, 2) as DistanceInKlms,
Registration, location, dateoffix
from
Positions
where
Geocolumn.STDistance(#g) is not null
and Registration = 'DX17AAF'
order by
Geocolumn.STDistance(#g);
Stored procedure breaks because of multiple columns:
select #return = (Select Top(1)
Round(GeographyPositon.STDistance(#g)/1000, 2) as DistanceInKlms,
Registration, [location], dateoffix
from Positions
WHERE Registration = #Registration
ORDER BY GeographyPositon.STDistance(#g))
do you need that?
select #return = (Select Top(1)
Round(GeographyPositon.STDistance(#g)/1000, 2)+' , '
Registration+' , '+ [location] +' , '+ dateoffix
from Positions
WHERE Registration = #Registration
ORDER BY GeographyPositon.STDistance(#g)
Try below to get all 4 column values in a single string.
select #return = ( Select Top(1)
CAST(Round(GeographyPositon.STDistance(#g)/1000, 2) AS VARCHAR)+', '
CAST(Registration AS VARCHAR)+', '+ CAST([location] AS VARCHAR) +', '+ CAST(dateoffix AS VARCHAR)
from Positions
WHERE Registration = #Registration
ORDER BY GeographyPositon.STDistance(#g) )

SQL string before and after certain characters

SELECT NAME
FROM SERVERS
returns:
SDACR.hello.com
SDACR
SDACR\AIR
SDACR.hello.com\WATER
I need the SELECT query for below result:
SDACR
SDACR
SDACR\AIR
SDACR\WATER
Kindly help ! I tried using LEFT and RIGHT functions as below, but not able to get combined output correctly:
SELECT
LEFT(Name, CHARINDEX('.', Name) - 1)
FROM
SERVERS
SELECT
RIGHT(Name, LEN(Name) - CHARINDEX('\', Name))
FROM
SERVERS
It looks like you're just trying to REPLACE a substring of characters in your column. You should try this:
SELECT REPLACE(Name,'.hello.com','') AS ReplacementName
FROM SERVERS
In tsql, you can concatenate values with CONCAT(), or you can simply add strings together with +.
SELECT LEFT(Name, CHARINDEX('.',Name)-1) + RIGHT(Name,LEN(Name)-CHARINDEX('\',Name)) from SERVERS
Also, be careful with doing arithmetic with CHARINDEX(). A value without a '.' or a '\' will return a NULL and you will get an error.
You can use LEFT for this to select everything up to the first period (dot) and add on everything after the last \
declare #servers table ([NAME] varchar(64))
insert into #servers
values
('SDACR.hello.com '),
('SDACR'),
('SDACR\AIR'),
('SDACR.hello.com\WATER')
select
left([NAME],case when charindex('.',[NAME]) = 0 then len([NAME]) else charindex('.',[NAME]) -1 end) +
case when charindex('\',left([NAME],case when charindex('.',[NAME]) = 0 then len([NAME]) else charindex('.',[NAME]) -1 end)) = 0 then right([NAME],charindex('\',reverse([NAME]))) else '' end
from #servers
Throwing my hat in.... Showing how to use Values and APPLY for cleaner code.
-- sample data in an easily consumable format
declare #yourdata table (txt varchar(100));
insert #yourdata values
('SDACR.hello.com'),
('SDACR'),
('SDACR\AIR'),
('SDACR.hello.com\WATER');
-- solution
select
txt,
newTxt =
case
when loc.dot = 0 then txt
when loc.dot > 0 and loc.slash = 0 then substring(txt, 1, loc.dot-1)
else substring(txt, 1, loc.dot-1) + substring(txt, loc.slash, 100)
end
from #yourdata
cross apply (values (charindex('.',txt), (charindex('\',txt)))) loc(dot,slash);
Results
txt newTxt
------------------------------ --------------------
SDACR.hello.com SDACR
SDACR SDACR
SDACR\AIR SDACR\AIR
SDACR.hello.com\WATER SDACR\WATER

SQL Server casting from a table

In SQL Server I have a query that looks like this (part of the WHERE clause of a larger query)
SELECT 1
WHERE TPR.GRDE_PK IN
(
SELECT CAST(String AS INT)
FROM dbo.Split_New(#GRADES, ',')
)
#Grades is equal to '14,15' and dbo.Split_New is a function that returns a table with a single column called String that will contains '14' and '15'. TPR.GRDE_PK is of type INT. I get a conversion error when I try to execute this line, can anyone tell me how to fix it?
Here is that the Split_New function looks like (Written by someone more skilled than me, so I don't understand all of it):
function [dbo].[Split_New] (
#StringToSplit nvarchar(4000),
#Separator varchar(128))
returns table as return
with indices as
(
select 0 S, 1 E
union all
select E, charindex(#Separator, #StringToSplit, E) + len(#Separator)
from indices
where E > S
)
select substring(#StringToSplit,S,
case when E > len(#Separator) then e-s-len(#Separator) else len(#StringToSplit) - s + 1 end) String
--,S StartIndex
from indices where S >0
The problem is your TPR.GRDE_PK value is an Integer, cast it as a VARCHAR():
SELECT 1
WHERE CAST(TPR.GRDE_PK AS VARCHAR(25)) IN
(
SELECT *
FROM dbo.Split_New(#GRADES, ',')
)
The function works fine, it returns the expected table of results given your string.
Alternatively, you can avoid using the function at all with LIKE:
WHERE ','+CAST(TPR.GRDE_PK AS VARCHAR(25))+',' LIKE '%,'+#GRADES+',%'
It is difficult to say exactly what it is without looking at the function.
First see if you get the correct results from the function:
SELECT String FROM dbo.Split_New(#GRADES, ',')
String may have leading/trailing spaces. Try to trim them before converting/casting using LTRIM() and RTRIM() function
SELECT CONVERT(INT, LTRIM(RTRIM(String))) FROM dbo.Split_New(#GRADES, ',')
ISNUMERIC() function is not ideal to filter and convert as it returns 1 for some characters that are not numbers.

SQL - ORDER BY in IF-ELSE CLAUSE

I have ONE table A and if the parameters #x is 0 i want to ordering A by date, else by Name.
This is an example:
declare #x int set #x = 0
if(#x=0)(
SELECT * FROM A
order by DATE
)
else
(
SELECT * FROM A
order by Name
)
When try to do it SQL Server return 2 egual error as
Incorrect syntax near the keyword 'order'.
What could i do?
Try this instead
SELECT * FROM A
order by
Case #x When 0 Then Cast(DATE as sql_variant) Else Name End
The casting is required for the dynamic sort to work with a date - I'm trying to find a reference, but you need a type that can be casted automatically to a common type, and date can't be done. Hence casting yourself.
Here's a link to some options. Note the section on mixed datatypes.
https://web.archive.org/web/20211029044050/https://www.4guysfromrolla.com/webtech/010704-1.shtml
declare #x int set #x = 0
if(#x=0)
begin
SELECT * FROM A
order by DATE
end
else
begin
SELECT * FROM A
order by Name
end
SELECT
*
FROM
A
ORDER BY
CASE WHEN #x = 0 THEN Date ELSE Name END
declare #x int
set #x = 0
IF (#x=0)
BEGIN
SELECT * FROM A order by DATE
END
ELSE
SELECT * FROM A order by Name
END
http://msdn.microsoft.com/en-us/library/aa933214(SQL.80).aspx
If your query becomes reasonably complex, then copying it into both sides of an IF/ELSE can becomes rather onerous. You can instead use a CASE expression in your ORDER BY. In this case, you might do:
SELECT * FROM A ORDER BY CASE WHEN #x=0 THEN DATE END, CASE WHEN #x<>0 THEN Name END
This can be expanded up to more conditions/columns. You just need to ensure that each CASE expression is returning a sensible data type.
Parentheses ( and ) are wrong. Use BEGIN and END instead.
DECLARE #x INT
SET #x = 0
IF (#x = 0) BEGIN
SELECT * FROM A ORDER BY DATE
END
ELSE BEGIN
SELECT * FROM A ORDER BY Name
END
Also, in my opinion, DATE as column name is not good idea.
As noted in the answers but not explained.
SQL uses BEGIN - END syntax instead of () or {} for block of commands

Resources