Need to use `IN` for multiple string value in static query - sql

SELECT *
FROM #empInfo
WHERE source IN (CASE WHEN #source = 'Mint' THEN 'Mint, Ming' ELSE #source END)
I am trying in the way as above.
CREATE TABLE #empInfo
(
id INT IDENTITY(1, 1),
ename VARCHAR(50),
source VARCHAR(50)
)
INSERT INTO #empInfo
VALUES ('Jon', 'Mint'), ('Jack', 'Ryan'), ('Jackie', 'Ming'),
('Jeny', 'Wing'), ('Jen', 'Wing')
DECLARE #source VARCHAR(50)
SET #source = 'Mint'
From the above what if want is, if the value Mint comes in the #source then it has to search for Mint,Ming else what comes in #source. #source always hold single value.
I have to apply this logic in very large query which is not dynamic nor I can make it, so please provide me the solution for this case if any.
Sorry, if it's not possible without dynamic query.
Thank you very much in advance.

SELECT * FROM #empInfo
WHERE (#source = 'Mint' and source in ('Mint','Ming'))
OR (#source <> 'Mint' and source = #source)
Remember that an IN clause needs separate string values. So you can't use a comma separated list in #source
A shorter version of the above query would be
SELECT * FROM #empInfo
WHERE #source = source
OR (#source = 'Mint' and source = 'Ming')

Related

How to list comma-seperated values of a given out from SQL program

To know doctors who have done 15 or more episodes from tables:
Table 1
and
I have written this code:
select
d.DoctorName
from
tblDoctor d, tblEpisode e
where
e.DoctorId = d.DoctorId
group by
d.DoctorId, d.doctorname
having
count(d.DoctorID) > 15;
My output:
Now I want to create a stored procedure which will output a variable containing a comma-delimited list of the doctors who have done 15 or more episodes.
Can someone help me how to do it?
You could create a stored procedure with an output parameter, and build something using this technique:
declare #test table (Name varchar(10));
insert into #test values ('Tom'),('Dick'),('Harry');
declare #result varchar(20) = '';
select #result = #result + ',' + name from #test
set #result = stuff(#result,1,1,'');
select isnull(#result,'')
But... as mentioned, csv lists are hardly the most useful of formats for returned data, so I would question that before you construct your SP.

SQL: how can I set a variable in this context?

I'm trying to set a couple of variables, one is a name of the table (#table), the other one is a string.
I've got the error message:
Must declare the table variable "#table".
as far as I could understand it's because I must use #table as a table variable, but I just need it as a string
declare #a varchar(50);
declare #table varchar(100);
select #table =
case
WHEN Version = 'Advanced' THEN ("tableadv")
WHEN Version = 'Professional' THEN ("tablepro")
WHEN Version = 'Light' THEN ("tablelight")
WHEN Version = 'Short' THEN ("tableshort")
END
FROM partno where inpn=3
set #a = (select top (1) LicenseNumber from #table where used is null)
insert into seriali (LicenseNumber, idpn, serdgtrace)
select #a, 2, 'DAT-enrico'
update #table set used = 1 where LicenseNumber=#a
any help will be appreciated.
Many thanks,
enrico
You need table variable not only variable to store more values with more columns not just single value :
declare #table table (
#col int,
. . .
)
insert into #table (col)
select case WHEN Version = 'Advanced' THEN 'tableadv'
WHEN Version = 'Professional' THEN 'tablepro'
WHEN Version = 'Light' THEN 'tablelight'
WHEN Version = 'Short' THEN 'tableshort'
end
from partno
where inpn = 3
hello Yogesh and thanks for the answer,
anyway I need this case structure to pick the right table name based on a field in another table.
Then I have to pass this value to update the right table;
set #a = (select top (1) LicenseNumber from #table where used is null)
update #table set used = 1 where LicenseNumber=#a
I don't need to build a table variable with one of the case values in a record, because I won't be able to pass the right table name either
Many thanks,
Enrico

How to make this stored procedure use a JSON check?

I am looking at using a stored procedure to help out with a situation of where I have to update/insert about a 1000 records. I was given the suggestion to use MERGE with a table-valued parameter to achieve this but the problem is one of the columns is a JSON string.
ItemsTbl
id -PK
BrandId- int (FK)
LocationId- int (FK)
Field3 - nvarchar(Max) Json string containing a jsonKey called itemNumber
select *
from ItemsTbl
where BrandId = 1
and LocationId = 1
and JSON_VALUE('Field3',$.itemNumber) = 12345
Now the stored procedure (what is pretty much all new to me) looks currently like this:
/* Create a table type. */
CREATE TYPE SourceTableType AS TABLE
( BrandId INT
, LocationId INT
, ItemNumber INT
, ...
);
GO
CREATE PROCEDURE dbo.usp_InsertTvp
#Source SourceTableType READONLY
AS
MERGE INTO Table1 AS Target
USING #Source As Source ON Target.BrandId = Source.BrandId
AND Target.LocationId = Source.LocationId
AND Target.ItemNumber = Source.ItemNumber
WHEN MATCHED THEN
UPDATE SET OtherParam = Source.OtherParam
WHEN NOT MATCHED BY TARGET THEN
INSERT (BrandId, LocationId, ItemNumber, OtherParam)
VALUES (BrandId, LocationId, ItemNumber, OtherParam) ;
The problem is this right now does not seem to account on that ItemNumber is inside a JSON string and not it's own column. So I don't think this would work
Target.ItemNumber = Source.ItemNumber
Also I am guessing SourceTableType would have to take in Field3 as a parameter and then extract it out itself?
I hope I understand you right.
Please try this:
;WITH MergeTarget AS (
SELECT t.BrandId,t.LocationId,t.Field3,JSON_VALUE(t.Field3,'$.itemNumber') AS [ItemNumber],t.OtherParam
FROM Table1 AS t
)
MERGE MergeTarget AS target
USING (
SELECT s.BrandId,s.LocationId,s.ItemNumber,'{"itemNumber":"'+CONVERT(NVARCHAR(255),s.ItemNumber)+'"' AS [Field3],s.OtherParam
FROM #Source AS s
) AS source ON source.BrandId = target.BrandId
AND source.LocationId = target.LocationId
AND source.ItemNumber = target.ItemNumber
WHEN MATCHED AND target.OtherParam <> source.OtherParam THEN UPDATE SET target.OtherParam = source.OtherParam
WHEN NOT MATCHED THEN INSERT (BrandId, LocationId, Field3, OtherParam)
VALUES(source.BrandId,source.LocationId,source.Field3,source.OtherParam)
;
Any questions also please let me know.

SQL Query data based on a variable

I have a simple query that I am trying to adapt to a new situation. For this situation, if the variable locationID=1 then I need all records, regardless of its locationID.
However, if it is not equal to 1, I need to only provide records that match that of the #locationID.
Here is my setup example:
DECLARE #locationID INT = 1; -- All Results Regardless of locationID
--DECLARE #locationID INT = 2; -- Only results that match this locationID (2)
--DECLARE #locationID INT = 3; -- Only results that match this locationID (3)
-- Temp Data
DECLARE #temp AS TABLE (color VARCHAR(10), locationID INT, name VARCHAR(20))
INSERT INTO #temp( color, locationID, name )VALUES ( 'Blue', 1, 'Test 1' )
INSERT INTO #temp( color, locationID, name ) VALUES ( 'Red', 2, 'Test 2' )
INSERT INTO #temp( color, locationID, name ) VALUES ( 'Red', 1, 'Test 3' )
INSERT INTO #temp( color, locationID, name ) VALUES ( 'Red', 2, 'Test 4' )
INSERT INTO #temp( color, locationID, name ) VALUES ( 'Red', 3, 'Test 5' )
-- Query
SELECT *
FROM #temp
WHERE
locationID = ...
I am trying to figure out if I need to use a CASE WHEN or some other method for this.
WHERE (locationID = #LocationId OR #locationID = 1)
Try this:
...WHERE (#LocationId = 1 AND 1=1)
OR (#LocationId <> 1 AND LocationId = #LocationId)
This seems devilishly simple, perhaps I am not understanding your question. If you want to query by a variable value, then just use the variable value:
DECLARE #LocationId INT = 1
SELECT *
FROM #temp
WHERE (#LocationId = 1 AND 1=1)
OR (#LocationId <> 1 AND LocationId = #LocationId)
A couple of other ideas. Since using a constant of 1 is not exactly intuitive or self-documenting, you could default that to NULL. And then say:
WHERE LocationID = COALESCE(#LocationID, LocationID);
If LocationID column is nullable, then instead you could use some token value that is at least slightly more self-documenting than 1, like -1 (since I don't think anyone looking at the code will immediately know that there isn't really a valid row where LocationID = 1):
WHERE LocationID = COALESCE(NULLIF(#LocationID, -1), LocationID);
This is susceptible to parameter sniffing, so you might want to add OPTION (RECOMPILE) if you find you are often switching between "all rows" and "very specific rows." You can also use dynamic SQL to optionally build the WHERE clause, assuming your real scenario uses a real table:
DECLARE #sql nvarchar(max) = N'SELECT ... FROM dbo.RealTable'
IF #LocationID <> 1 -- or IS NOT NULL or <> -1 or what have you
BEGIN
SET #sql += N' WHERE LocationID = #LocationID';
END
EXEC sys.sp_executesql #sql, N'#LocationID int', #LocationID;
This way you get a different plan when the parameter is included vs. when it is not, which doesn't really make the scan (where you need all rows) any better, but it guards against the case where you use a seek + lookup against all rows, which can be really bad. More often, it prevents you from getting the dreadful full table/index scan when you really could have used a seek. But which way that goes is completely dependent on which case is more likely the first time the query runs.
And even here you may want to use OPTION (RECOMPILE) at the end of #sql if the distribution of data across different LocationID values is (or might later become) heavily skewed.
I call this type of query "the kitchen sink," and have written about it here:
#BackToBasics : An Updated "Kitchen Sink" Example
So the variable should be 1 or the locationid?
You could use an IN for that.
... WHERE #LocationID IN (1, LocationID)
Example snippet:
declare #locationID int;
-- Test data using a table variable
declare #varTable table (id int identity(1,1) primary key, locationID int, name varchar(20), color varchar(10));
insert into #varTable (locationID, name, color) values
(1,'Test 1','Blue'),
(2,'Test 2','Red'),
(1,'Test 3','Red'),
(2,'Test 4','Red'),
(3,'Test 5','Red');
-- Returning all records
set #locationID = 1;
SELECT t.* FROM #varTable t WHERE #locationID IN (1, t.locationID);
-- Only returning those with locationID = 2
set #locationID = 2;
SELECT t.* FROM #varTable t WHERE #locationID IN (1, t.locationID);

Removing ' ' from sql query and stored proc

I have a table in which a column named data is of type varbinary . If I do a simple query
select * from tab where data = 1 then it works but if I do select * from tab where data = '1' then it does not return any row. The issue comes when I create a stored proc to retrieve data from this table and it converts the query and adds ' ' in the parameter when querying and so I am not able to retrieve any data. Can some one please tell me how to get around this issue.
Parameters
#ID INT = NULL
,#Data varchar(100) = NULL
CREATE TABLE #Results (
ID INT
,Data varchar(100)
)
BEGIN
INSERT #Results (
ID
,Data
)
SELECT
SK.ID
,SK.Data
FROM dbo.tab SK
where SK.ID = #ID And SK.data = #data
END
SELECT #TotalRows = COUNT(*)
FROM #Results
SELECT #TotalRows TotalRows
Now from the code when I execute this statement
oReader = ExecuteReader(oConn, CommandType.StoredProcedure, "Proc", New SqlParameter("#ID", Request.ID), _
New SqlParameter("#Data", Request.Data))
I see in SQL Profiler that it runs the query as 'data'
which does not return any rows
Thanks
Since you have said that you have written an SP, I think the inpput parameter is specified as NVARCHAR or VARCHAR
Below is one way of doing but i'm guessing that the column called data will only have integer values in the first solution.
DECLARE #X VARCHAR(5)
SET #X = '1 '
SELECT CAST(#X AS INT)
The above is only if the Data column specified above is Integer.
If the same is string (VARCHAR) you can write a User defined function to do the same.
CREATE FUNCTION dbo.TRIM(#string VARCHAR(8000))
RETURNS VARCHAR(8000)
BEGIN
RETURN LTRIM(RTRIM(#string))
END
SELECT dbo.TRIM('1 ')
I hope the above was useful, I did get the idea rather copied the function from here
http://blog.sqlauthority.com/2007/04/24/sql-server-trim-function-udf-trim/