How to ask where with calling function? - SQL Server - sql

I want to ask a Function in the where clause.
The code:
SELECT * FROM MyTable
WHERE Field1=10
and dbo.MyFunction(Field2,Field3,Field4) = NULL
And this returns me an empty table even though there are correct values in the table, why is this happening? What could be the reason?

SELECT * FROM MyTable
WHERE Field1=10
and dbo.MyFunction(Field2,Field3,Field4) **is** NULL
and not = NULL

You need to define like dbo.MyFunction(Field2,Field3,Field4) is NULL instead of dbo.MyFunction(Field2,Field3,Field4) = NULL
SELECT * FROM MyTable
WHERE Field1=10
and dbo.MyFunction(Field2,Field3,Field4) is NULL

In SQL you have to use is null or is not null instead = null.
I suggest you do not use function in your where clause it is not a good practice. You can use cte as below:
with
cte
as
(
select
* ,
dbo.MyFunction(Field2,Field3,Field4) as [your_function_field]
from
MyTable
where
Field1=10
)
where
[your_function_field] is null

Related

Conditional statements in "WHERE" in SQL Server

What I want to achieve is to have a switch case in the where clause. I want to test if this statement returns something, if it returns null, use this instead.
Sample:
SELECT [THIS_COLUMN]
FROM [THIS_TABLE]
WHERE (IF THIS [ID] RETURNS NULL THEN DO THIS SUBQUERY)
What I mean is that it will do this query first.
SELECT [THIS_COLUMN]
FROM [THIS_TABLE]
WHERE [ID] = 'SOMETHING'
If this returns NULL, do this query instead:
SELECT [THIS_COLUMN]
FROM [THIS_TABLE]
WHERE ID = (SELECT [SOMETHING] FROM [OTHER_TABLE]
WHERE [SOMETHING_SPECIFIC] = 'SOMETHING SPECIFIC')
Note that the expected results from the intended query varies from 30 rows up to 15k rows. Hope it helps.
Adding more information:
The results for this query will be used for another query but will just focus on this query.
Providing a real case scenario:
[THIS_COLUMN] is expected to have a list of VALUES.
[THIS_TABLE] contains the latest data only(let's say 1 year's worth of data) while the [OTHER_TABLE] contains the historical data.
What I want to achieve is when I query for a data that is not with in the 1 year's worth of data, IE 'SOMETHING' is not with in the 1 year scope(or in my case it returns NULL), I will use the other query where I query the 'SOMETHING_SPECIFIC'(Or may be 'SOMETHING' from the first statement makes more sense) from the historical table.
If I as reading through the lines correctly, this might work:
SELECT THIS_COLUMN
FROM dbo.THIS_TABLE TT
WHERE TT.ID = 'SOMETHING'
OR TT.ID = (SELECT OT.SOMETHING
FROM dbo.OTHER_TABLE OT
WHERE OT.SOMETHING_SPECIFIC = 'SOMETHING SPECIFIC'
AND NOT EXISTS (SELECT 1
FROM dbo.THIS_TABLE sq
WHERE sq.ID = 'SOMETHING'
AND THIS_COLUMN IS NOT NULL))
Note, however, that this could easily not be particularly performant.
You an use union all and not exists:
select this_column
from this_table
where id = 'something'
union all
select this_column
from this_table
where
not exists (select this_column from this_table where id = 'something')
and id = (select something from other_table where something_specific = 'something specific')
The first union member attempts to find rows that match the first condition, while the other one uses the subquery - the not exists prevents the second member to return something if the first member found a match.
90% of the time you can use a query-batch (i.e. a sequence of T-SQL statements) in a single SqlCommand object or SQL Server client session, so with that in-mind you could do this:
DECLARE #foo nvarchar(50) = (
SELECT
[THIS_COLUMN]
FROM
[THIS_TABLE]
WHERE
[ID] = 'SOMETHING'
);
IF #foo IS NULL
BEGIN
SELECT
[THIS_COLUMN]
FROM
[THIS_TABLE]
WHERE
[ID] = (
SELECT
[SOMETHING]
FROM
[OTHER_TABLE]
WHERE
[SOMETHING_SPECIFIC] = 'SOMETHING SPECIFIC'
)
END
ELSE
BEGIN
SELECT #foo AS [THIS_COLUMN];
END
That said, SELECT ... FROM ... WHERE x IN ( SELECT y FROM ... ) is a code-smell in a query - you probably need to rethink your solution entirely.

NVL Column and NULL

I have rows as shown below
ProductId ProductName ProductDesc ProductLoc
101 Camel Pencil B-10
102 Parker Pen
103 Mirado Pen C-10
When I execute the following SQL query
SELECT *
FROM tablename
WHERE productloc = NVL ('', productloc)
It gives me the 1st and 3rd row, what I would like to achieve is if productloc is null in where condition of the SQL, then I should get all three rows.
How can I get the desired output.
select * from tablename;
Is what you need in that case because your where gives no effect. You compare column with itself.
If you want to filter and include nulls you can do (but probably replace one productloc with some value:
select * from tablename where productloc = productloc or productloc is null;
Or:
select * from tablename where nvl(productloc, 'SOME_UNIQUE_VAL') = nvl(productloc, 'SOME_UNIQUE_VAL');
and also replace one of productloc by some value.
Try something like :
SELECT *
FROM tablename
WHERE nvl(productloc,'zzz') = (case when productloc is null then 'zzz' else productloc end )
Here zzz is some dummy value, which otherwise should not be present as value in particular column.
I suppose three different solutions:
If you want all rows (with productloc null and valued) you can write the following query:
SELECT *
FROM tablename
Without WHERE clause.
If you want extract all rows with productloc has a specified value or is null, so you can write the following query:
SELECT *
FROM tablename
WHERE productloc IS NULL OR productloc = YOURVARIABLE
or (the last, without use OR condition)
SELECT *
FROM tablename
WHERE NVL(productloc, YOURVARIABLE) = YOURVARIABLE
I assume you are using Oracle. In Oracle "NULL" is not a value and because of it any compare function will return false.
I recomend:
SELECT *
FROM tablename
WHERE (productloc = productloc OR productloc IS NULL)
Hope it helps,
Sérgio

IsNull is slow, do I have other option?

Having the following query:
select
tA.Name
,tA.Prop1
,tA.Prop2
( select sum(tB.Values)
from tableB tB
where tA.Prop1 = tB.Prop1
and tA.Prop2 = tB.Prop2
) as Total
from tableA tA
This query is taking me 1 second to run, BUT it will give me wrong SUM when Prop2 is null
I change the query to use IsNULL
and ISNULL(tA.Prop2,-1) = ISNULL(tB.Prop2,-1)
the data is correct now, but takes almost 7 seconds.....
Is there a fastest way to do this?
Note: this is just a partial simplified version of a more complex query.... but the base idea is here.
From your description, = is using an index, but the isnull() blocks the use of an index. This is a bit hard to get around in SQL server.
One way is to break the logic into two sums:
select tA.Name, tA.Prop1, tA.Prop2
(isnull((select sum(tB.Values)
from tableB tB
where tA.Prop1 = tB.Prop1 and tA.Prop2 = tB.Prop2
), 0) +
isnull((select sum(tB.Values)
from tableB tB
where tA.Prop1 = tB.Prop1 and
tA.Prop2 is null and tB.Prop2 is null
), 0)
) as Total
from tableA tA;
I ended up using
AND (
(tA.Prop2= tB.Prop2)
OR (tA.Prop2 IS NULL AND tB.Prop2 IS NULL )
)

SQL. How should i write NOT LIKE statement

SELECT *
FROM [Table]
WHERE (Izdava NOT LIKE NULL)
// how to check if Izdava is not NULL
This should work:
SELECT * FROM [Table] WHERE Izdava IS NOT NULL
SELECT * FROM [Table] WHERE (Izdava IS NOT NULL)
LIKE NULL is meaningless. It doesn't make sense. LIKE is used for comparing a partial string using wildcards, or a complete string without wildcards.
Depending on the RDBMS you want NOT IS NULL,
SELECT * FROM [Table] WHERE (NOT Izdava IS NULL)
I think this is what you want.
SELECT *
FROM [Table]
WHERE Izdara Is Not NULL
Information about NULL values from MSDN:
Following is information about nulls:
To test for null values in a query, use IS NULL or IS NOT NULL in the
WHERE clause.
If you are checking for not null, dont use the like clause. Just write
select * from tablename where columnmame is not null
If it's MSSQL or Oracle then do this:
SELECT *
FROM [Table]
WHERE Izdava IS NOT NULL

return a default record from a sql query

I have a sql query that I run against a sql server database eg.
SELECT * FROM MyTable WHERE Id = 2
This may return a number of records or may return none. If it returns none, I would like to alter my sql query to return a default record, is this possible and if so, how? If records are returned, the default record should not be returned. I cannot update the data so will need to alter the sql query for this.
Another way (you would get an empty initial rowset returned);
SELECT * FROM MyTable WHERE Id = 2
IF (##ROWCOUNT = 0)
SELECT ...
SELECT TOP 1 * FROM (
SELECT ID,1 as Flag FROM MyTable WHERE Id = 2
UNION ALL
SELECT 1,2
) qry
ORDER BY qry.Flag ASC
You can have a look to this post. It is similar to what you are asking
Return a value if no rows are found SQL
I hope that it can guide you to the correct path.
if not exists (SELECT top 1 * FROM mytable WHERE id = 2)
select * from mytable where id= 'whatever_the_default_id_is'
else
select * from mytable where id = 2
If you have to return whole rows of data (and not just a single column) and you have to create a single SQL query then do this:
Left join actual table to defaults single-row table
select
coalesce(a.col1, d.col1) as col1,
coalesce(a.col2, d.col2) as col2,
...
from (
-- your defaults record
select
default1 as col1,
default2 as col2,
...) as d
left join actual as a
on ((1 = 1) /* or any actual table "where" conditions */)
The query need to return the same number of fields, so you shouldn't do a SELECT * FROM but a SELECT value FROM if you want to return a default value.
With that in mind
SELECT value FROM MyTable WHERE Id = 2
UNION
SELECT CASE (SELECT count(*) FROM MyTable WHERE Id = 2)
WHEN 0 THEN 'defaultvalue'
END