how to use declared variable to select data from another table in case when condition? - sql

I made select query in which i want to select data based on condition.For this i declared one variable and set value of that variable in else part.I want to use that variable for further select in same else part how can i achieve this?Please Help
declare #stateid int
select CASE WHEN MstCustomerAddressInfo.StateId is null
THEN 24
ELSE set #stateid = MstCustomerAddressInfo.StateId
select mststate.statecode from mststate where MstState.StateId = #stateid
END AS StateCode

No, you can't have SET inside a CASE expression. Even you can't have multiple statements.
Same query you can write as following.
declare #stateid int
select CASE
WHEN MstCustomerAddressInfo.StateId is null THEN 24
ELSE
-- set #stateid = MstCustomerAddressInfo.StateId
(select mststate.statecode
from mststate
where MstState.StateId = MstCustomerAddressInfo.StateId)
END AS StateCode
from [Your_Table]

Related

Use variable sql for column name

Before you shout at me in CAPS for not searching - I have! Dynamic SQL is good, dynamic SQL is bad. Learning a lot..
I can accomplish what I'm after by using logic in there WHERE clause, but it adds a significant amount of run time. The query takes 8 seconds if I hard code the criteria and 1:20 if I use the WHERE logic.
Here is what I'd like to do:
Declare #EmployeeToggle varchar(30)
Declare #Employee_ID varchar(30)
Declare #EmployeeField varchar(100)
set #EmployeeToggle = '1'
set #Employee_ID = '1166'
set #EmployeeField = case when #EmployeeToggle = '1' then 'Field1' else
'Field2' end;
select * from Table1 where #EmployeeField = #Employee_ID
I don't think it's possible without dynamic sql. I still don't know whether or not I should use it. It's my thought that it would take the query back down to 8 seconds, because it would immediately know which field to use in the where clause.
Alternatively, a few ways to do it in the where only:
where (( not #EmployeeToggle = '1') or Field1 = #Employee_ID) and
(#EmployeeToggle = '1' or Field2 = #Employee_ID)
where (1=(case when #EmployeeToggle = '1' then 1 else 0 end ) or Field1 =
#Employee_ID)
and (1=(case when #EmployeeToggle = '2' then 1 else 0 end) or Field2 =
#Employee_ID)
These work great (admittedly I copied and pasted these examples), but at the expense of run time.
My final thought, and the way others have done it at my org, is to create two scripts that are identical except for the field used in the where clause. So, if #EmployeeToggle = '1' it will run the first script and if it's '2' it will run the second. I haven't tried that yet, but I assume the runtime will be closer to the 8 seconds at the expense of some ugly code.
Thanks for the help.
Why not just use a single query?
select t.*
from table1
where #EmployeeToggle = '1' and field_1 = #Employee_ID
union all
select t.*
from table1
where #EmployeeToggle <> '1' and field_2 = #Employee_ID;
By using union all, SQL Server should use indexes for each subquery -- and if you have indexes on the fields, the query should be fast.
You can stay with static SQL when using CASE expression in SELECT then filter it.
SELECT *
FROM (
SELECT *,
CASE WHEN #EmployeeToggle = '1' THEN Field1 ELSE Field2 END AS Field1_2
FROM Table1
) t
WHERE
Field1_2 = #Employee_ID
Here is your dynamic query:
Declare #EmployeeToggle varchar(30)
Declare #Employee_ID varchar(30)
Declare #EmployeeField varchar(100)
set #EmployeeToggle = '1'
set #Employee_ID = '1166'
set #EmployeeField = case when #EmployeeToggle = '1' then 'Field1' else
'Field2' end;
DECLARE #SQLString VARCHAR(MAX)
SET #SQLString='select *
from Table1
where '+#EmployeeField+' = '+#Employee_ID+''
PRINT(#SQLString) --If you want to check actual query
EXEC(#SQLString)

How to find out sum of a column with respect to another columns maximum and minimum

I have worked with DB2, and I just moved to the SQL Server. I'm a bit confused by a query.
Lets suppose I have table data like
StoreID | Sales
A | 23
B | 50
B | 50
In this data with the stored procedure parameter, I wanted to roll up the sum of Sales. I will get a parameter of StoreID, but in this parameter I can get 'ALL' too.
In DB2 I can get all data using a stored procedure (which has StoreID in a parameter named ParameterStore) with a query like
if(ParameterStore= 'ALL') Then
Set Loc_min = X'00';
Set Loc_max = X'FF';
ELSE
Set Loc_min = ParameterStore;
Set Loc_max = ParameterStore;
END if;
Select Sum(Sales) From Store_data where StoreID between Loc_min and Loc_max;
How can I do this in SQL Server to get the same result?
You could check the value if it's ALL or some other value in OR:
DECLARE #store_id VARCHAR(20) -- or whatever length you have
SET #store_id = 'XYZ'
select sum(sales)
from store_data
where #store_id = 'ALL' or store_id = #store_id;
T-SQL syntax for IF is slightly different. You can use it like this:
/*
DECLARE #ParameterStore VARCHAR(10);
DECLARE #Loc_min INT;
DECLARE #Loc_max INT;
*/
IF #ParameterStore = 'ALL'
BEGIN
Set #Loc_min = 0x00;
Set #Loc_max = 0xFF;
END
ELSE
BEGIN
Set #Loc_min = #ParameterStore;
Set #Loc_max = #ParameterStore;
END;
Having said that, what you are trying to achieve could be done as follows:
-- DECLARE #ParameterStore VARCHAR(10);
SELECT SUM(Sales)
FROM Store_data
WHERE CASE
WHEN #ParameterStore = 'ALL' THEN -1
WHEN #ParameterStore = StoreID THEN -1
END = -1
Try this if you need hexadecimal comparison.
DECLARE
#ParameterStore VARCHAR(10)
SET #ParameterStore = 'ALL'
SELECT SUM(Sales)
FROM Store_data
WHERE StoreID BETWEEN (
CASE
WHEN #ParameterStore = 'ALL'
THEN 0x00
ELSE #ParameterStore
END)
AND (
CASE
WHEN #ParameterStore = 'ALL'
THEN 0xFF
ELSE #ParameterStore
END ) ;
DEMO

SQL Filter SELECT statement

I need to filter my select statement to only grab a value is a bit value is true. For example
DECLARE
#Value AS NVARCHAR(20) = 'Some Value'
#BIT AS BIT = 1,
#Stuff AS NVARCHAR(20) = 'Stuff'
SELECT
#Stuff,
IF #BIT = 1 BEGIN #Value END ELSE BEGIN '' END
Something like this basically. I only want to select the value if its true. I have multiple checkboxes and the data should only pull that data back if the user selects one of those check boxes so I'm using bit's to track if its checked or not. Thanks in advance
Use CASE not IF:
SELECT
#Stuff,
CASE WHEN #BIT = 1 THEN #Value ELSE '' END
or
CASE #BIT WHEN 1 THEN #Value ELSE '' END
It's a little unclear what you are trying to do, so I will give you several approaches:
If you are limiting your select statement, you can do:
SELECT ...
FROM ...
WHERE myBitField = 1
or, if your bit field is a variable that's being passed in, you can do:
SELECT ...
FROM ...
WHERE myBitField = #BIT
If you don't want to limit your select results, you can use a case statement:
SELECT CASE WHEN #BIT = 1 THEN #Value ELSE '' END as BitResult
FROM ...

SQL Table Valued Function in Select Statement

SQL is not my best thing but I have been trying to optimize this stored procedure. It had multiple scalar-valued functions that I tried to change to table-valued functions because I read in many places that it's a more efficient way of doing it. And now I have them made but not real sure how to implement or if I maybe just didn't create them correctly.
This is the function I'm calling.
Alter FUNCTION [IsNotSenateActivityTableValue]
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
returns #T table(result varchar(max))
as
begin
DECLARE #result varchar(max);
declare #countcodes int;
declare #ishousebill int;
select #ishousebill = count(billid)
from BillMaster
where BillID = #BillID and Chamber = 'H'
If (#ishousebill = 0)
begin
SELECT #countcodes = count([ActivityCode])
FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%' and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
if (#countcodes = 0)
begin
set #result = 'test'
end
else
begin
set #result = 'test2'
end
end
else
begin
set #result = #TextToDisplay
end
RETURN
END
And this is how I was trying to call them like this. I would prefer just being able to put them in the top but really anything that works would be good.
SELECT distinct
ActionDates.result as ActionDate
,ActivityDescriptions.result as ActivityDescription
FROM BillWebReporting.vwBillDetailWithSubjectIndex as vw
left outer join [BillWebReporting].[HasHouseSummary] as HasSummary on vw.BillID = HasSummary.BillID
outer APPLY dbo.IsNotSenateActivityDateTableValue(ActivityCode,vw.BillID,[ActionDate]) ActionDates
OUTER APPLY dbo.IsNotSenateActivityTableValue(ActivityCode,vw.BillID,[ActivityDescription]) as ActivityDescriptions
Getting a count just to see if at least one row exists is very expensive. You should use EXISTS instead, which can potentially short circuit without materializing the entire count.
Here is a more efficient way using an inline table-valued function instead of a multi-statement table-valued function.
ALTER FUNCTION dbo.[IsNotSenateActivityTableValue] -- always use schema prefix!
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN (SELECT result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = #BillID AND Chamber = 'H'
) THEN #TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
) THEN 'test2' ELSE 'test' END
END);
GO
Of course it could also just be a scalar UDF...
ALTER FUNCTION dbo.[IsNotSenateActivityScalar] -- always use schema prefix!
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #result VARCHAR(MAX);
SELECT #result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = #BillID AND Chamber = 'H'
) THEN #TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
) THEN 'test2' ELSE 'test' END
END;
RETURN (#result);
END
GO
Table-valued functions return a table, in which, like any other table, rows have to be inserted.
Instead of doing set #result = ....., do:
INSERT INTO #T (result) VALUES ( ..... )
EDIT: As a side note, I don't really understand the reason for this function to be table-valued. You are essentially returning one value.
First of all UDFs generally are very non-performant. I am not sure about MySQL, but in Sql Server a UDF is recompiled every time (FOR EACH ROW OF OUTPUT) it is executed, except for what are called inline UDFs, which only have a single select statement, which is folded into the SQL of the outer query it is included in... and so is only compiled once.
MySQL does have inline table-valued functions, use it instead... in SQL Server, the syntax would be:
CREATE FUNCTION IsNotSenateActivityTableValue
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN
(
Select case
When y.bilCnt + z.actCnt = 0 Then 'test'
when y.bilCnt = 0 then 'test2'
else #TextToDisplay end result
From (Select Count(billId) bilCnt
From BillMaster
Where BillID = #BillID
And Chamber = 'H') y
Full Join
(Select count([ActivityCode]) actCnt
From [HouseCoreData].[dbo].[ActivityCode]
Where ActivityDescription not like '%(H)%'
And ActivityType = 'S'
And [ActivityCode] = #ActivityCode) z
)
GO

SQL SERVER: Check if variable is null and then assign statement for Where Clause

I am trying to achieve something like the below in WHERE clause in sql.
if (#zipCode ==null)
begin
([Portal].[dbo].[Address].Position.Filter(#radiusBuff) = 1)
end
else if(#zipCode !=null)
begin
([Portal].[dbo].[Address].PostalCode=#zipCode )
end
I tried the following:
WHERE ((#zipCode IS NOT NULL AND ([Portal].[dbo].[Address].PostalCode=#zipCode)) OR (#zipCode IS NULL AND ([Portal].[dbo].[Address].Position.Filter(#radiusBuff) = 1)))
which is wrong. Can anyone help in framing the exact statement. Thanks!
is null is the syntax I use for such things, when COALESCE is of no help.
Try:
if (#zipCode is null)
begin
([Portal].[dbo].[Address].Position.Filter(#radiusBuff) = 1)
end
else
begin
([Portal].[dbo].[Address].PostalCode=#zipCode )
end
Isnull() syntax is built in for this kind of thing.
declare #Int int = null;
declare #Values table ( id int, def varchar(8) )
insert into #Values values (8, 'I am 8');
-- fails
select *
from #Values
where id = #Int
-- works fine
select *
from #Values
where id = isnull(#Int, 8);
For your example keep in mind you can change scope to be yet another where predicate off of a different variable for complex boolean logic. Only caveat is you need to cast it differently if you need to examine for a different data type. So if I add another row but wish to specify int of 8 AND also the reference of text similar to 'repeat' I can do that with a reference again back to the 'isnull' of the first variable yet return an entirely different result data type for a different reference to a different field.
declare #Int int = null;
declare #Values table ( id int, def varchar(16) )
insert into #Values values (8, 'I am 8'), (8, 'I am 8 repeat');
select *
from #Values
where id = isnull(#Int, 8)
and def like isnull(cast(#Int as varchar), '%repeat%')
is null can be used to check whether null data is coming from a query as in following example:
declare #Mem varchar(20),#flag int
select #mem=MemberClub from [dbo].[UserMaster] where UserID=#uid
if(#Mem is null)
begin
set #flag= 0;
end
else
begin
set #flag=1;
end
return #flag;
Try a case statement
WHERE
CASE WHEN #zipCode IS NULL THEN 1
ELSE #zipCode
END
Try the following:
if ((select VisitCount from PageImage where PID=#pid and PageNumber=5) is NULL)
begin
update PageImage
set VisitCount=1
where PID=#pid and PageNumber=#pageno
end
else
begin
update PageImage
set VisitCount=VisitCount+1
where PID=#pid and PageNumber=#pageno
end