Is there such thing as a conditional operator in SQL Server? - sql-server

I have the below SQL code snippet and I want to select sales from all customers by manipulating the value of the #Customer parameter. Is there any way to do this in SQL Server 2008 R2? I've tried setting #Customer = '%' but obviously that didn't work since there is no LIKE operator.
I only want to manipulate the parameter because there will be other times where I will
need to select only a single customer. Is there such a thing as using an IF/ELSE in the WHERE clause?
DECLARE #Customer varchar(5) = ''
SELECT *
FROM SalesData
WHERE Customer=#Customer

Is there such a thing as using an IF/ELSE in the WHERE clause
Absolutely, there is a CASE expression - not only in the WHERE clause, but also in other parts of your query. However, a more common approach is to use logical expressions in the WHERE clause that force SQL Server to take one condition or the other depending on the parameter setting.
my condition would be if #Customer = '' then select all
If you would like to select all customers when the parameter is set to empty, or select all customers where the parameter is not set, you can do this:
SELECT *
FROM SalesData
WHERE #Customer = ''
OR Customer = #Customer
If #Customer is set to '', the first clause of the OR expression will be TRUE for all rows, so all customers would be returned. However, when #Customer is non-empty, the second part of the expression would be evaluated.

Not quite sure how you need to perform search
But can try something like below
SELECT *
FROM SalesData
WHERE Customer like '%' + #Customer + '%'
Or
SELECT *
FROM SalesData
WHERE (LEN(#Customer)>0 AND Customer =#Customer)
OR (LEN(#Customer)=0)
In here I havent trim assuming you always pass ''. But you can always use LEN(LTRIM(RTRIM(#Customer)))

If you default #Customer to NULL rather than '' then you could just have
WHERE Customer = ISNULL(#Customer, Customer)

Related

Set where clause basis parameter value in SQL Server

I wish to set a condition while making use of the WHERE clause basis #USER_ID input recorded from the user in my SQL server query, but I guess I am missing something essential here.
DECLARE #USER_ID NVARCHAR(255) = 'a,b,c' -- will be multi-select parameter; can be null as well
select * from <table_name>
{
if: #USER_ID is NULL then no WHERE condition
else: WHERE <table_name>.<col_name> in (SELECT item FROM SplitString(#USER_ID,','))
}
Can someone please help here?
Personally, I would suggest switching to a table type parameter, then you don't need to use STRING_SPLIT at all. I'm not going to cover the creation of said type of parameter here though; there's plenty already out there and the documentation is more than enough to explain it too.
As for the problem, if we were to be using STRING_SPLIT you would use a method like below:
SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
WHERE YT.YourColumn IN (SELECT SS.Value
FROM STRING_SPLIT(#USER_ID,',') SS)
OR #USER_ID IS NULL
OPTION (RECOMPILE);
The RECOMPILE in the OPTION clause is important, as a query where #USER_ID has the value NULL is likely to be very different to that where it isn't.
You could use a dynamic SQL approach, but for one parameter, I doubt there will more anything more than a negligible benefit. Using the above is much easier for others to understand as well, and the cost of generating the plan every time the query is run should be tiny for such a simple query.
Using a table type parameter, it would actually likely be more performant (assuming you have a useable index on YourColumn) to use a UNION ALL query like the below:
SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
JOIN #Users U ON YT.YourColumn = U.UserId
UNION ALL
SELECT {Your Columns} --Don't use *
FROM dbo.YourTable YT
WHERE NOT EXISTS (SELECT 1 FROM #Users U);
You could avoid using STRING_SPLIT entirely here:
WHERE ',' + #USER_ID + ',' LIKE '%,' + <table_name>.<col_name> + ',%'
If the #UserID is NULL, then the condition (1=1) is executed, this is always true. If the #UserID is not NULL, then the OR condition is executed in which all <col_name> in (a, b, c) are present.
SELECT *
FROM <table_name>
WHERE (1=1)
AND ((#USER_ID IS NULL AND (1=1)) -- always true
OR (<table_name>.<col_name> in (SELECT [value] FROM SplitString(#USER_ID,',')))
)

Manipulate a string to be used in IN operator (SQL, SSRS)

I have an SSRS report with dataset that has query looking like this (simplified as the query is a lot more complex that this):
select *
from myTable
where country in (#Country)
#Country is a parameter and can have multiple values
It works fine, but we were asked to roll up all the values from one country to another one (the country is not in the list of parameters to be selected).
So for example we need to roll up all the records that belong to Canada to US if US was selected as one of the Countries essentially just replacing 'Canada' with 'US' in the dataset returned which is easy to achieve using REPLACE or even CASE statement. However, it gets a bit tricky with WHERE clause in the query. Does anyone know how to replace a string with another string so it's understood by IN operator?
If I simply do something like this:
select *
from myTable
where country in (replace(#Country, 'US', 'US,Canada'))
the query doesn't return anything and I understand the reasons behind it.
If I test this hardcoding the values like this:
select *
from myTable
where country in ('US', 'Canada')
it returns the correct rows of data. I think I'm looking for a way to join multiple values so it's understood properly by IN operator.
TIA,
-TS.
You can use Dynamic SQL to achieve this. All you need to do is pass country name in declaration at first line.
Look at the code below:
DECLARE #SQL NVARCHAR(2000), #Country VARCHAR(30) = 'Canada'
SELECT #SQL = CONCAT('
select
*
from myTable
where country in (',
CASE WHEN #Country = 'US' THEN '''US'', ''Canada''' else '#Country' end , ')'
)
EXEC sp_executesql #SQL, N'#Country VARCHAR(30)', #Country = #Country
Here's a fiddle : http://sqlfiddle.com/#!18/b7f49/4
Possibly the same answer as SQL in (#Variable) query
You may need to add REPLACE to that function based on your requirements.

select value into variable and alias in SQL Server

I'd like to simultaneously do two things in an MSSQL query:
select a field's value into a variable
select #myvar = colName from tableName
alias my column
select colName as [myCol] from tableName
I've tried these things:
Attempted Syntax select #myvar = colName as [myCol] from tableName
Attempted Syntax select #myvar = (colName as [myCol]) from tableName
Attempted Syntax select (#myvar = colName) as [myCol] from tableName
checked select statement syntax: https://msdn.microsoft.com/en-us/library/ms176104.aspx
If this is possible, how can it be accomplished?
A select can either assign values to variables or return column values, but not both.
In some cases, e.g. when using select to provide data to an insert, an output clause may be useful. A tool well worth having in your pocket as it provides access to identity values from insert and both before and after values when used with update.

SQL Single Value or All

For report purposes in SSRS I need an SQL query for one parameter which will select only one value or all values (not two or more). It's a single value parameter.
Well, my query should looks like this, but it didn't work:
SELECT ft.id, ft.name
FROM fundtable ft
UNION ALL
SELECT '11111111-1111-1111-1111-111111111111','All'
DECLARE #funds NVARCHAR(MAX)
SELECT #funds = COALESCE(CAST(entity_id AS NVARCHAR(255)),',')
FROM epev_conduit
SELECT #funds
If you are using this query for a dataset that your parameter is using for the Available Values, you don't need to put in into a string. Just use:
select ft.id, ft.name
from fundtable ft
union all
Select '11111111-1111-1111-1111-111111111111','All'
The use your Name field for the Label and your ID for the Value. You can Specify a Default value expression of
="11111111-1111-1111-1111-111111111111"
if you want the default to be all.
This should do the trick.
SELECT *
FROM dbo.YourTable
WHERE #id = id
OR #id = '11111111-1111-1111-1111-111111111111'

Is there a way to optimize the query given below

I have the following Query and i need the query to fetch data from SomeTable based on the filter criteria present in the Someothertable. If there is nothing present in SomeOtherTable Query should return me all the data present in SomeTable
SQL SERVER 2005
SomeOtherTable does not have any indexes or any constraint all fields are char(50)
The Following Query work fine for my requirements but it causes performance problems when i have lots of parameters.
Due to some requirement of Client, We have to keep all the Where clause data in SomeOtherTable. depending on subid data will be joined with one of the columns in SomeTable.
For example the Query can can be
SELECT
*
FROM
SomeTable
WHERE
1=1
AND
(
SomeTable.ID in (SELECT DISTINCT ID FROM SomeOtherTable WHERE Name = 'ABC' and subid = 'EF')
OR
0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC' and subid = 'EF')
)
AND
(
SomeTable.date =(SELECT date FROM SomeOtherTable WHERE Name = 'ABC' and subid = 'Date')
OR
0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC' and subid = 'Date')
)
EDIT----------------------------------------------
I think i might have to explain my problem in detail:
We have developed an ASP.net application that is used to invoke parametrize crystal reports, parameters to the crystal reports are not passed using the default crystal reports method.
In ASP.net application we have created wizards which are used to pass the parameters to the Reports, These parameters are not directly consumed by the crystal report but are consumed by the Query embedded inside the crystal report or the Stored procedure used in the Crystal report.
This is achieved using a table (SomeOtherTable) which holds parameter data as long as report is running after which the data is deleted, as such we can assume that SomeOtherTable has max 2 to 3 rows at any given point of time.
So if we look at the above query initial part of the Query can be assumed as the Report Query and the where clause is used to get the user input from the SomeOtherTable table.
So i don't think it will be useful to create indexes etc (May be i am wrong).
SomeOtherTable does not have any
indexes or any constraint all fields
are char(50)
Well, there's your problem. There's nothing you can do to a query like this which will improve its performance if you create it like this.
You need a proper primary or other candidate key designated on all of your tables. That is to say, you need at least ONE unique index on the table. You can do this by designating one or more fields as the PK, or you can add a UNIQUE constraint or index.
You need to define your fields properly. Does the field store integers? Well then, an INT field may just be a better bet than a CHAR(50).
You can't "optimize" a query that is based on an unsound schema.
Try:
SELECT
*
FROM
SomeTable
LEFT JOIN SomeOtherTable ON SomeTable.ID=SomeOtherTable.ID AND Name = 'ABC'
WHERE
1=1
AND
(
SomeOtherTable.ID IS NOT NULL
OR
0=(SELECT Count(1) FROM SomeOtherTable WHERE spName = 'ABC')
)
also put 'with (nolock)' after each table name to improve performance
The following might speed you up
SELECT *
FROM SomeTable
WHERE
SomeTable.ID in
(SELECT DISTINCT ID FROM SomeOtherTable Where Name = 'ABC')
UNION
SELECT *
FROM SomeTable
Where
NOT EXISTS (Select spName From SomeOtherTable Where spName = 'ABC')
The UNION will effectivly split this into two simpler queries which can be optiomised separately (depends very much on DBMS, table size etc whether this will actually improve performance -- but its always worth a try).
The "EXISTS" key word is more efficient than the "SELECT COUNT(1)" as it will return true as soon as the first row is encountered.
Or check if the value exists in db first
And you can remove the distinct keyword in your query, it is useless here.
if EXISTS (Select spName From SomeOtherTable Where spName = 'ABC')
begin
SELECT *
FROM SomeTable
WHERE
SomeTable.ID in
(SELECT ID FROM SomeOtherTable Where Name = 'ABC')
end
else
begin
SELECT *
FROM SomeTable
end
Aloha
Try
select t.* from SomeTable t
left outer join SomeOtherTable o
on t.id = o.id
where (not exists (select id from SomeOtherTable where spname = 'adbc')
OR spname = 'adbc')
-Edoode
change all your select statements in the where part to inner jons.
the OR conditions should be union all-ed.
also make sure your indexing is ok.
sometimes it pays to have an intermediate table for temp results to which you can join to.
It seems to me that there is no need for the "1=1 AND" in your query. 1=1 will always evaluate to be true, leaving the software to evaluate the next part... why not just skip the 1=1 and evaluate the juicy part?
I am going to stick to my original Query.

Resources