I have a handful of scalar-valued functions (which I appreciate may not be best practice, but for now, this will suffice, this is simply a development exercise) which I use within various computed columns with MS SQL tables.
I have a scenario whereby I need to use the result of one of these functions, as a parameter to another within a given computed column. For example;
(case when [DynamicQuantity] IS NULL then ([dbo].[GetFiatValue]([Currency],[Quantity])) ELSE ([dbo].[GetFiatValue]([Currency],([dbo].[getStakedQuantity]([currency])))) end)
If the given [DynamicQuantity] field is null (a column value generated by another SVF), use the [Quantity] field. However, if [DynamicQuantity] is populated, the ELSE will fire, and pass the output of the [dbo].[getStakedQuantity] SVF in place of the [Quantity] value.
Is this achievable? I can't seem to get the syntax to work and am questioning whether this is even possible?
Running it via a normal query works;
SELECT case when [DynamicQuantity] IS NULL then [dbo].[GetFiatValue]([Currency],[Quantity]) ELSE [dbo].[GetFiatValue]([Currency],[dbo].[getStakedQuantity]([currency])) end from dbo.cryptoPortfolio
But when used as a computed column formula below;
case when [DynamicQuantity] IS NULL then [dbo].[GetFiatValue]([Currency],[Quantity]) ELSE [dbo].[GetFiatValue]([Currency],[dbo].[getStakedQuantity]([currency])) end
SSMS will not accept it, with Error validating the formula for column 'FiatValue'.
Related
I have a table with two columns hora_entrada and hora_saida and when running this select statement:
select hora_entrada, hora_saida
from Controlo_de_Entrada_saidas
it shows this result:
What I want to do is to combine these two columns into one that if Hora_saida = "Não saiu", it shows the data in hora_entrada but if hora_saída has an actual hour in there, it shows the data in hora_saida instead.
So basically this should be my result:
I don't know if I'm making myself clear, I actually don't even know where to start or if its even possible but any help would be appreciated.
Try using a CASE expression:
SELECT
hora_entrada,
hora_saida,
CASE WHEN hora_saida = 'Não saiu'
THEN hora_entrada ELSE hora_saida END AS new_column
FROM yourTable;
This logic assumes that any value in the hora_saida column which is not Não saiu is a valid timestamp. If not, then we could add additional logic to check for this as well.
If you are open/able to changing your data model, you might want to consider just storing NULL values for the missing data. SQL Server (and most other databases as well) has a built-in function COALESCE, which can be used to replace NULL with a backup value. This would avoid needing to use a lengthy CASE expression as you see above.
Trying to run this query in LINQPad 4:
SELECT item_group_id as AccountID, IIF(ISNULL(t_item_group.description),'[blank]',t_item_group.description) AS Name
FROM t_item_group
WHERE active = TRUE
I get, "the isnull function requires 2 argument(s)."
I've tried moving the parens around, changing the "[blank]" to "[blank]" and "[blank]" , but none of it helps...
The queries (I have two similar ones (with IIF(ISNULL)) that LINQPad won't run for this reason, yet they run in actuality (in my Web API app) fine; so, LINQPad is more "picky" than it needs to be, perhaps, but what is it expecting, SQL syntax-wise?
ISNULL is already like a 'if' type statement.
You can just replace
IIF(ISNULL(t_item_group.description),'[blank]',t_item_group.description)
with
ISNULL(t_item_group.description, '[blank]')
The ISNULL uses the first parameter (the 'description'), unless that value is null in which case it will use the second parameter.
As an aside, one of the reasons I don't care for ISNULL is that it is poorly named. You'd assume that given its name it will return a bit - true if the parameter is null, false if not null - which you could use in an 'if' statement like you attempted. But that's not how it works.
The alternative is to use COALESCE. It provides much the same functionality, but the naming makes sense.
co·a·lesce ˌkōəˈles verb
1. come together and form one mass or whole.
To COALESCE two parameters is to force them into one non-nullable result. And the function is actually more powerful, as you can provide multiple parameters - COALESCE(i.description, i.name, '[blank]') is perfectly valid.
I have developed one report using SSRS Report Builder. The report contains several parameters in which one of the parameter contains NULL values apart from the values that it fetches from the database.
Now when I select NON-NULL values from that parameter the report runs fine because I'm using IN Clause (as the parameter values are multi-select). But when I select NULL (and not any other values) from that parameter, the IN clause doesn't works as IN doesn't take NULL.
Hence what/how should I modify my query so that it could handle both --- NULL and NON-NULL Values?
The following forces all NULLs to be included and makes it clear to the user of the report that the value is missing:
SELECT ISNULL([ColumnNameHere],'[ None ]') AS [ColumnNameHere]
WHERE ISNULL([ColumnNameHere],'[ None ]') IN (#MultiParam)
I have run into this problem before.
The solution is not to pass NULL, but to pass a default value that in reality, your DB never uses. It's not ideal, but seems to be a quirk of the implementation.
So, in the case where you're searching for ThingId. ThingId is a surrogate key that we know can never be >0.
You use the 0 as your value for any, and pass it instead of NULL, then change your query like so:-
WHERE
#ThingId = 0 OR ThingId = #ThingId
I have a indexed view where I basically need to do this
SELECT ...
CASE
WHEN ISDATE(ColumnName) = 1 THEN CONVERT(datetime, ColumnName, 103)
ELSE NULL
END AS ViewColumn
....
Trying to create the index yields:
Cannot create index on view
'....'. The function
'isdate' yields nondeterministic results. Use a deterministic system
function, or modify the user-defined function to return deterministic
results.
MSDN says
ISDATE is deterministic only if you use it with the CONVERT function,
if the CONVERT style parameter is specified, and style is
not equal to 0, 100, 9, or 109.
here http://msdn.microsoft.com/en-us/library/ms187347.aspx.
But I don't know what that means at all. As far as I can tell, I am using it with a CONVERT function....
Any way to work around this?
It should be, if at all:
SELECT ...
CASE
WHEN ISDATE(ColumnName) = 1 THEN CONVERT(datetime, ColumnName, 103)
ELSE NULL
END
....
but, you are not using ISDATE WITH CONVERT, since there is no expression like
ISDATE(CONVERT(varchar,ColumnName,112))
without the nested convert the return value is dependend on things like language settings, hence it's nondeterministic behaviour. Without "external" knowledge, it's not possible to predict the result one is getting, based on the input alone.
Reference
What are the requirements for Indexed views?
There are several requirements that you must take into consideration when using Indexed views.
1. View definition must always return the same results from the same underlying data.
2. Views cannot use non-deterministic functions.
3. The first index on a View must be a clustered, UNIQUE index.
4. If you use Group By, you must include the new COUNT_BIG(*) in the select list.
5. View definition cannot contain the following
(A) TOP
(B) Text, ntext or image columns
(C)DISTINCT
(d)MIN, MAX, COUNT, STDEV, VARIANCE, AVG
(E)SUM on a nullable expression
(F)A derived table
(G)Rowset function
(H)Another view
(I)UNION
(J)Subqueries, outer joins, self joins
(K)Full-text predicates like CONTAIN or FREETEXT
(L)COMPUTE or COMPUTE BY
(M)Cannot include order by in view definition
For those of you who have actually delt with RETS may be able to give me a hand here. The problem occurs when multiple properties are tied into the RETS data even though the property is sold. Basically what I need is to be able to check the database with the SELECT statement against three fields. The fields in question would be C_StreetName, C_StreetNumber, and C_PostalCode.
To make this clear what I want is some type of way to check for duplicates while gathering the dataset, this can't be done in php because of how the data is returned through the application. So if it finds another record with the same C_StreetName, C_StreetNumber, and C_PostalCode it will remove them from the dataset. Ideally it would be nice if it could also check the Status of the two to find out if one is Expired or Sold before removing them from the data.
I'm not familiar with complex SQL functions, I was looking at the IF statement until I found that can only be used while storing data not the other way around. And the CASE statement but it just doesn't seem like that would work.
If you guys have any suggestions on what I should use I'd appreciate it. Hopefully there is a way to do this and keep in mind this is only one table I am accessing I don't have any Joins.
Thanks in advance.
Here's something to get you going in the right direction. I haven't tested this, and am not sure you can nest a case expression inside max() in mysql.
What this accomplishes is to output one row per unique combination of street name, number and postcode, with a status of 'Expired' or 'Sold' taking precedence over other values. That is, if there's a row with 'Expired' it will be output in preference to non-expired and non-sold, and a row with 'Sold' will be output if it exists, regardless of what other rows exist for that property. The case statement just converts the status codes into something orderable.
select
C_StreetName,
C_StreetNumber,
C_PostalCode,
max(
case status
when 'Expired' then 1
when 'Sold' then 2
else 0
end) as status
group by
C_StreetName,
C_StreetNumber,
C_PostalCode;