2Im in a big trouble, im refactoring a very big procedure to full text search, and I found a very important outer apply:
select top 1 *
from tablea
where
column1 like
case
when #value = 1 or #value = 2 then '%' + #something + '%'
else '%'
end
The logic here is: if #value is 1 or 2, get the first register with #something inside. Else, get any register.
What I need now is:
select top 1 *
from tablea
where
case
when #value = 1 or #value = 2 then contains(column1, #something)
else 1 = 1
end
The code above dont work, its mal formed, and I have no clue how solve that.
select top 1 *
from tablea
where
(#value IN (1,2) AND (#something = '""' OR contains(column1, #something)))
OR #value NOT IN (1,2)
Related
I want to get multipule choises after then in case statment as
#value
select * from [dbo].[Currency_Tbl]
WHERE [Currency_Active_YN]=
CASE WHEN #value = 1 THEN
( 1 or 0)
ELSE
#Value = 0 then 0
END
it didn't accept the first line in col1 but accept the col2
how can I select multiple numbers after THEN?
You don't use case in where clauses. Use boolean logic
select * from [dbo].[Currency_Tbl]
WHERE (#value = 1 and [Currency_Active_YN] in (0,1))
OR (#value = 0 and [Currency_Active_YN] = 0)
You dont need a case to do what you're trying to do. Assuming Currency_Active_YN is a not null bit field the following logic should suffice.
select * from [dbo].[Currency_Tbl]
WHERE (#value=1 OR [Currency_Active_YN]=#Value)
i've been searching SO for a while and found nothing related to this.
We use heavily the dynamic approach for most of our queries like this:
Declare #ContactId VarChar(8000)
Select #ContactId = '1'
Select *
From Person.Contact
Where 1 = 1 And
Case When Len(Ltrim(Rtrim(#ContactId))) = 0 Then 1 Else ContactID End =
Case When Len(Ltrim(Rtrim(#ContactId))) = 0 Then 1 Else #ContactId End
This way the query gets filtered dynamically if there's a value on the parameter
But the problem comes when trying the same stuff with several IDs like so:
Declare #ContactId VarChar(8000)
Select #ContactId = '1,2,3'
Select *
From Person.Contact
Where 1 = 1 And
Case When Len(Ltrim(Rtrim(#ContactId))) = 0 Then 1 Else ContactID End In (
Select Case When Len(Ltrim(Rtrim(#ContactId))) = 0 Then 1 Else ( Select id From dbo.SplitString(#ContactId,',') ) End )
Sql throws an error "Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
that's totally normal and expected, my question is:
Is there a way to dynamically do this kind of filtering ?
The solution we use is this:
Declare #Table Table(
Col1 Int,
Col2 Int,
Col3 Int
)
Insert #Table
Select Col1, Col2, Col3
From Person.Contact
Where [many filters except the in clause filters]
If Len(Ltrim(RTrim(#ContactId))) > 0
Select *
From #Table
Where ContactId In ( Select Id From dbo.SplitString(#ContactId, ',') )
Else
Select *
From #Table
But it's not an option when the query is massive and feeding a table variable is overkill for this. Hope i made my point and someone is kind enough to help me find a solution to this.
PS: Using sp_ExecuteSql is not an option in this scenario either, sorry.
How you should do this is with a table parameter.
But if you want to persist in this approach.
Declare #ContactId VarChar(8000)
Select #ContactId = '1,2,3'
Select *
From Person.Contact
where ',' + #contactID + ',' like '%,'+convert(varchar(50),contactid)+',%'
Try this
Select *
From Person.Contact
Where (
len(#contactid) > 0 AND
ContactID IN (Select id From dbo.SplitString(#ContactId,',')))
or 1 = 1
I have more than 3 sql tables.
now i'm trying to select count(*) from all tables but how can i do this?.
I want to know whether data is present in all tables or not
I need to check the row count from previous business day ~15% for any table and it sends an email alert
I tried like following please help me to complete
PROCEDURE [dbo].[SendEmail_WSOTableDataAlert]
AS
BEGIN
declare #err int
IF NOT EXISTS (select 1 from T1) OR
NOT EXISTS (select 1 from T2)
BEGIN
set #error=1
END
//here i need to show which table is having empty data how can i do this please help
SET #tableHTML = #tableHTML + +
'</TABLE>' + #EmailFooter;
#error =1
then
send mail
END
Select
case when count(*) = 0 then
'No rows'
else
'Has rows'
end
FROM
(
Select * from #table1
UNION ALL
Select * from #table2
UNION ALL
Select * from #table3
) t
UPDATE
This makes sure all of then have at least one row and fail if any of them does not have record
Select
case when count(*) = 0 then
'No rows'
else
'Has rows'
end
FROM
(
Select top 1 1 found from #table1
intersect
Select top 1 1 found from #table2
intersect
Select top 1 1 found from #table3
) t
You can try multiplying the flags indicating zero counts together. If any of them is zero, the result will be zero.
select (case when (select count(*) from table1)=0 then 0 else 1 end
*case when (select count(*) from table2)=0 then 0 else 1 end
*case when (select count(*) from table3)=0 then 0 else 1 end) as no_zeros
If you would like to know which table has all zeros, you could transform the query as follows:
select (case when (select count(*) from table1)=0 then 1 else 0 end
+case when (select count(*) from table2)=0 then 2 else 0 end
+case when (select count(*) from table3)=0 then 4 else 0 end
+case when (select count(*) from table4)=0 then 8 else 0 end) as no_zeros
Use powers of two (1, 2, 4, 8, 16, 32, and so on) as your flags. Ones 1 in the binary representation of the result will tell you which tables have no records.
(select count() from table1 )
union all
(select count() from table2 )
union all
(select count(*) from table3 )
And then loop through the rows of the result
declare #count1 int
select #count1 = count(*)
from table1
declare #count2 int
select #count2 = count(*)
from table2
declare #count3 int
select #count3 = count(*)
from table3
if (#count1 + #count2 + #count3 = 0)
--do something
else
--do something else
You can use the EXISTS keyword to efficiently check if there is any data in a table.
IF NOT EXISTS (SELECT 1 FROM Table1) OR NOT EXISTS (SELECT 1 FROM Table2) OR NOT EXISTS (SELECT 1 FROM Table3)
BEGIN
/* do something */
END
How to know if all the cells have the same value in some column (title changed)
I want to have a bit scalar value that tells me if all the values in a column equal something:
DECLARE #bit bit
SELECT #bit = TRUEFORALL(Name IS NOT NULL) FROM Contact
UPDATE
I now realized that I actually don't need the TrueForAll, what I do need is to make sure, that all values in a column are equal, for example, I want to know whether all Group.Items have the same price.
Why not?
select count( distinct price) from table
If returns 1, all values are the same... Add
where price is not null
if need be
For your updated requirement something like this would appear to do what you want:
DECLARE #IsSameGroup bit
SELECT #IsSameGroup = CASE WHEN COUNT(*) > 1 THEN 0 ELSE 1 END
FROM (SELECT Name FROM Contact GROUP BY Name) groups
When the count is greater the 1 you have two different names (or prices depending on what you group on)
Not very good for NULLs, but 2008 can do:
SELECT 1 WHERE 'Blue' = ALL ( SELECT Color FROM dbo.Hat )
OR
DECLARE #bit bit
SET #bit =
CASE ( SELECT 1 WHERE 'Blue' = ALL ( SELECT Color FROM dbo.Hat ))
WHEN 1 THEN 1 ELSE 0 END
UPDATE
All same color
SET #bit =
CASE(
SELECT 1 WHERE
(SELECT TOP(1) Color FROM dbo.Hat) = ALL ( SELECT Color FROM dbo.Hat )
)
WHEN 1 THEN 1 ELSE 0 END
Maybe this?
DECLARE #bit bit
if exists(SELECT Name FROM Contact WHERE Name IS NULL)
SET #bit = 0
ELSE
SET #bit = 1
This solves your first question:
SELECT
CASE
WHEN EXISTS(
SELECT 1
FROM Contact
WHERE Name IS NULL
) THEN 0
ELSE 1
END
ADDED:
This will solve your second:
SELECT
CASE
WHEN EXISTS(
SELECT TOP 1 1 FROM (
SELECT
ItemGroupName,
COUNT(Price) AS CNT
FROM ItemGroup
GROUP BY ItemGroupName
HAVING COUNT(Price) > 1
) t
) THEN 0
ELSE 1
END
By the way, when you use the exists function, its better to SELECT 1 (a constant) so less data gets returned
Is it possible to use an IF clause within a WHERE clause in MS SQL?
Example:
WHERE
IF IsNumeric(#OrderNumber) = 1
OrderNumber = #OrderNumber
ELSE
OrderNumber LIKE '%' + #OrderNumber + '%'
Use a CASE statement
UPDATE: The previous syntax (as pointed out by a few people) doesn't work. You can use CASE as follows:
WHERE OrderNumber LIKE
CASE WHEN IsNumeric(#OrderNumber) = 1 THEN
#OrderNumber
ELSE
'%' + #OrderNumber
END
Or you can use an IF statement like #N. J. Reed points out.
You should be able to do this without any IF or CASE
WHERE
(IsNumeric(#OrderNumber) AND
(CAST OrderNumber AS VARCHAR) = (CAST #OrderNumber AS VARCHAR)
OR
(NOT IsNumeric(#OrderNumber) AND
OrderNumber LIKE ('%' + #OrderNumber))
Depending on the flavour of SQL you may need to tweak the casts on the order number to an INT or VARCHAR depending on whether implicit casts are supported.
This is a very common technique in a WHERE clause. If you want to apply some "IF" logic in the WHERE clause all you need to do is add the extra condition with an boolean AND to the section where it needs to be applied.
You don't need a IF statement at all.
WHERE
(IsNumeric(#OrderNumber) = 1 AND OrderNumber = #OrderNumber)
OR (IsNumeric(#OrderNumber) = 0 AND OrderNumber LIKE '%' + #OrderNumber + '%')
There isn't a good way to do this in SQL. Some approaches I have seen:
1) Use CASE combined with boolean operators:
WHERE
OrderNumber = CASE
WHEN (IsNumeric(#OrderNumber) = 1)
THEN CONVERT(INT, #OrderNumber)
ELSE -9999 -- Some numeric value that just cannot exist in the column
END
OR
FirstName LIKE CASE
WHEN (IsNumeric(#OrderNumber) = 0)
THEN '%' + #OrderNumber
ELSE ''
END
2) Use IF's outside the SELECT
IF (IsNumeric(#OrderNumber)) = 1
BEGIN
SELECT * FROM Table
WHERE #OrderNumber = OrderNumber
END ELSE BEGIN
SELECT * FROM Table
WHERE OrderNumber LIKE '%' + #OrderNumber
END
3) Using a long string, compose your SQL statement conditionally, and then use EXEC
The 3rd approach is hideous, but it's almost the only think that works if you have a number of variable conditions like that.
Use a CASE statement instead of IF.
You want the CASE statement
WHERE OrderNumber LIKE
CASE WHEN IsNumeric(#OrderNumber)=1 THEN #OrderNumber ELSE '%' + #OrderNumber END
To clarify some of the logical equivalence solutions.
An if statement
if (a) then b
is logically equivalent to
(!a || b)
It's the first line on the Logical equivalences involving conditional statements section of the Logical equivalence wikipedia article.
To include the else, all you would do is add another conditional
if(a) then b;
if(!a) then c;
which is logically equivalent to
(!a || b) && (a || c)
So using the OP as an example:
IF IsNumeric(#OrderNumber) = 1
OrderNumber = #OrderNumber
ELSE
OrderNumber LIKE '%' + #OrderNumber + '%'
the logical equivalent would be:
(IsNumeric(#OrderNumber) <> 1 OR OrderNumber = #OrderNumber)
AND (IsNumeric(#OrderNumber) = 1 OR OrderNumber LIKE '%' + #OrderNumber + '%' )
I think that where...like/=...case...then... can work with Booleans. I am using T-SQL.
Scenario: Let's say you want to get Person-30's hobbies if bool is false, and Person-42's hobbies if bool is true. (According to some, hobby-lookups comprise over 90% of business computation cycles, so pay close attn.).
CREATE PROCEDURE sp_Case
#bool bit
AS
SELECT Person.Hobbies
FROM Person
WHERE Person.ID =
case #bool
when 0
then 30
when 1
then 42
end;
// an example for using a stored procedure to select users filtered by country and site
CREATE STORED PROCEDURE GetUsers
#CountryId int = null,
#SiteId int = null
AS
BEGIN
SELECT *
FROM Users
WHERE
CountryId = CASE WHEN ISNUMERIC(#CountryId) = 1 THEN #CountryId ELSE CountryId END AND
SiteId = CASE WHEN ISNUMERIC(#SiteId) = 1 THEN #SiteId ELSE SiteId END END
// take from the input countryId AND/OR siteId if exists else don't filter
WHERE (IsNumeric(#OrderNumber) <> 1 OR OrderNumber = #OrderNumber)
AND (IsNumber(#OrderNumber) = 1 OR OrderNumber LIKE '%'
+ #OrderNumber + '%')
CASE Statement is better option than IF always.
WHERE vfl.CreatedDate >= CASE WHEN #FromDate IS NULL THEN vfl.CreatedDate ELSE #FromDate END
AND vfl.CreatedDate<=CASE WHEN #ToDate IS NULL THEN vfl.CreatedDate ELSE #ToDate END
WHERE OrderNumber LIKE CASE WHEN IsNumeric(#OrderNumber) = 1 THEN #OrderNumber ELSE '%' + #OrderNumber END
In line case Condition will work properly.
In sql server I had same problem I wanted to use an and statement only if parameter is false and on true I had to show both values true and false so I used it this way
(T.IsPublic = #ShowPublic or #ShowPublic = 1)
The following example executes a query as part of the Boolean expression and then executes slightly different statement blocks based on the result of the Boolean expression. Each statement block starts with BEGIN and completes with END.
USE AdventureWorks2012;
GO
DECLARE #AvgWeight decimal(8,2), #BikeCount int
IF
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%' ) > 5
BEGIN
SET #BikeCount =
(SELECT COUNT(*)
FROM Production.Product
WHERE Name LIKE 'Touring-3000%');
SET #AvgWeight =
(SELECT AVG(Weight)
FROM Production.Product
WHERE Name LIKE 'Touring-3000%');
PRINT 'There are ' + CAST(#BikeCount AS varchar(3)) + ' Touring-3000 bikes.'
PRINT 'The average weight of the top 5 Touring-3000 bikes is ' + CAST(#AvgWeight AS varchar(8)) + '.';
END
ELSE
BEGIN
SET #AvgWeight =
(SELECT AVG(Weight)
FROM Production.Product
WHERE Name LIKE 'Touring-3000%' );
PRINT 'Average weight of the Touring-3000 bikes is ' + CAST(#AvgWeight AS varchar(8)) + '.' ;
END ;
GO
Using nested IF...ELSE statements
The following example shows how an IF … ELSE statement can be nested inside another. Set the #Number variable to 5, 50, and 500 to test each statement.
DECLARE #Number int
SET #Number = 50
IF #Number > 100
PRINT 'The number is large.'
ELSE
BEGIN
IF #Number < 10
PRINT 'The number is small'
ELSE
PRINT 'The number is medium'
END ;
GO
If #LstTransDt is Null
begin
Set #OpenQty=0
end
else
begin
Select #OpenQty=IsNull(Sum(ClosingQty),0)
From ProductAndDepotWiseMonitoring
Where Pcd=#PCd And PtpCd=#PTpCd And TransDt=#LstTransDt
end
See if this helps.
USE AdventureWorks2012;
GO
IF
(SELECT COUNT(*) FROM Production.Product WHERE Name LIKE 'Touring-3000%' ) > 5
PRINT 'There are more than 5 Touring-3000 bicycles.'
ELSE PRINT 'There are 5 or less Touring-3000 bicycles.' ;
GO