using multi-value parameter with delimited string in dataset - sql

I have a table that contains a field with a delimited string, This is in fact a unsorted list of id's
id| name | valueslist
----------------------------------------------
1 | John | 46423423,36456325,76473234,98798796
2 | Mike | 36456325,98798796
3 | Sara | 46423423
I have a multi-value parameter based on a dataset that lists all possible id's
param: #chosenvalues
possible values:
46423423
36456325
76473234
98798796
Now, when selecting on or more id's in the parameter, I want to return all records from my table that have that value present in their valueslist.
eg:
If I select 36456325 I need John & Mike to be returned
If I select 46423423 I need John & Sara to be returned
If I select 46423423 & 98798796 I need all three to be returned
I thought I could solve this like
SELECT * FROM table WHERE '%' + valueslist + '%' IN ('%' + #chosenvalues + '%')
but that doesn't work. Any suggestions as to how I could solve this?
TIA,
Henro
edit: I know this is in fact far from ideal modeling but unfortunately it is what I have to work with.

Please try the following SQL Select statement
/*
create table valueslisttbl (id smallint, name varchar(20), valueslist varchar(1000))
insert into valueslisttbl values
(1, 'John', '46423423,36456325,76473234,98798796'),
(2, 'Mike', '36456325,98798796'),
(3, 'Sara', '46423423')
*/
declare #chosenvalues varchar(100)
--set #chosenvalues = '46423423'
--set #chosenvalues = '36456325'
--set #chosenvalues = '76473234'
set #chosenvalues = '46423423,98798796'
select distinct name
from valueslisttbl
cross apply dbo.Split(valueslisttbl.valueslist, ',') s
where s.val in (
select val from dbo.Split(#chosenvalues, ',')
)
Also note that you need a SQL Split function in order to solve your requirement
I used SQL XML for the above SQL Server split function where you can find the SQL source codes at http://www.kodyaz.com/articles/t-sql-convert-split-delimeted-string-as-rows-using-xml.aspx
I hope it helps,

And suddenly I was struck by lightning and the idea came to me in a blinding flash of genius. (Well, it FELT that way anyway)
I joined the table with john's and janes to the table with all the possible solutions. I then did a select distinct using a real standard where clause
SELECT DISTINCT j.*
FROM tableJohn j
LEFT JOIN Table_Solutions s on '%'+ s.value + '%' LIKE j.valuelist
WHERE s.value in (#chosen_values)
#chosen_values could now nicely be populated with values from a multi-value parameter in a SSRS report.

Related

Search using LIKE operator with multiple dynamic values accepting both full and partial text match

Is there any way to do multiple term search in a column using like operator dynamically in SQL Server? Like below
SELECT ID
FROM table
WHERE
Company LIKE '%goog%' OR
Company LIKE '%micros%' OR
Company LIKE '%amazon%'
For example: input values "goog; micro; amazon;" (input value should auto split by delimiter ';' and check the text exist in the table) means that Search term 'goog' or 'micros' or 'amazon' from company column, if exists return.
Table - sample data:
ID Company
------------------------------------------
1 Google; Microsoft;
2 oracle; microsoft; apple; walmart; tesla
3 amazon; apple;
4 google;
5 tesla;
6 amazon;
Basically, The above query should return the results as like below,
Desired results:
ID
-----
1
2
4
6
Is it possible to achieve in SQL Server by splitting, then search in query? I look forward to an experts answer.
If you pass in a table valued parameter, you can join on that.
So for example
CREATE TYPE StringList AS TABLE (str varchar(100));
DECLARE #tmp StringList;
INSERT #tmp (str)
VALUES
('%goog%'),
('%micros%'),
('%amazon%');
SELECT t.ID
FROM table t
WHERE EXISTS (SELECT 1
FROM #tmp tmp
WHERE t.Company LIKE tmp.str);
The one issue with this is that someone could write le; Mic and still get a result.
Strictly speaking, your table design is flawed, because you are storing multiple different items in the same column. You really should have this normalized into rows, so every Company is a separate row. Then your code would look like this:
SELECT t.ID
FROM table t
JOIN #tmp tmp ON t.Company LIKE tmp.str
GROUP BY t.ID
You can simulate it by splitting your string
SELECT t.ID
FROM table t
WHERE EXISTS (SELECT 1
FROM STRING_SPLIT(t.Company) s
JOIN #tmp tmp ON s.value LIKE tmp.str);

Combine Multiple Rows Into A Single Column

I am working on a stored procedure for reporting purposes and I need to combine rows in a single column but I can't find a way to do this. I have four tables, Case, Debtor, DebtorAddress and CaseNote. Rather than try to do this in a single statement I decided to create a temp table with the columns needed, populate the ones that occupy a single row, then use an update statement to combine the multiple rows of the last column needed into a single row. My temp table has rows for CApKey (the ID of the Case table), OwnerName (from Debtor), Address (from DebtorAddress, and Note. For each Case there may be multiple Notes (stored in the CaseNote table). So I may have Case #1, with a CApKey value of 1, OwerName of John Jones, Address of 1234 Main St. There may be one Note the says 'Called and left message', another that says 'Sent letter', and another that says 'Left a second voicemail', etc. I'd like to combine the three notes into a single row with Note values of Called and left a message, Sent Letter, and Left a second voicemail. I can use space, period, or comma as a delimiter. I found a way to do the update in theory but I'm getting an error that the sub-query returned more than 1 value. Below is the "heart" of the procedure. I've been wracking my brain on this for two days now. Any assistance is greatly appreciated in advance. Here is the statement I'm trying:
CREATE TABLE #temp
(
CaseKey int,
OwnerName varchar(500),
Address varchar(500),
Note varchar(MAX)
)
DECLARE #val Varchar(MAX);
INSERT INTO #temp
(CaseKey, OwnerName, Address)
SELECT ca.CApKey, DEFirstName + ' ' + DELastName, da.DAAddress1
FROM [Case] ca INNER JOIN Debtor de ON ca.CApKey = de.CApKey INNER JOIN DebtorAddress da ON ca.CApKey = da.CApKey
WHERE ca.LFpKey = #LFpKey AND de.DEIsPrimary = 1
UPDATE #temp SET Note =
(SELECT COALESCE(#val + ', ' + CANNote, CANNote)
FROM CaseNote WHERE CApKey = 51)
--SELECT #val;)
SELECT * FROM #temp
Thanks!
If i understood you correctly, you need to combine all the notes.
Get your data, queried from the 4 tables into a table (ex. #t)
Then you can use XML PATH and Stuff to achieve your goal (later you can use that for whatever your purpose as inserting to a table or display in a report etc)
SELECT CaseKey, OwnerName, Address, (STUFF((
SELECT ', ' + Note
FROM #t tx
where tx.CaseKey = t.CaseKey and tx.OwnerName = t.OwnerName and tx.Address = t.Address
FOR XML PATH('')
), 1, 2, '')
) AS StringValue
From #t t
Group by CaseKey, OwnerName, Address
Here is the fiddle

SQL Server where condition on column with separated values

I have a table with a column that can have values separated by ",".
Example column group:
id column group:
1 10,20,30
2 280
3 20
I want to create a SELECT with where condition on column group where I can search for example 20 ad It should return 1 and 3 rows or search by 20,280 and it should return 1 and 2 rows.
Can you help me please?
As pointed out in comments,storing mutiple values in a single row is not a good idea..
coming to your question,you can use one of the split string functions from here to split comma separated values into a table and then query them..
create table #temp
(
id int,
columnss varchar(100)
)
insert into #temp
values
(1,'10,20,30'),
(2, '280'),
(3, '20')
select *
from #temp
cross apply
(
select * from dbo.SplitStrings_Numbers(columnss,',')
)b
where item in (20)
id columnss Item
1 10,20,30 20
3 20 20
The short answer is: don't do it.
Instead normalize your tables to at least 3NF. If you don't know what database normalization is, you need to do some reading.
If you absolutely have to do it (e.g. this is a legacy system and you cannot change the table structure), there are several articles on string splitting with TSQL and at least a couple that have done extensive benchmarks on various methods available (e.g. see: http://sqlperformance.com/2012/07/t-sql-queries/split-strings)
Since you only want to search, you don't really need to split the strings, so you can write something like:
SELECT id, list
FROM t
WHERE ','+list+',' LIKE '%,'+#searchValue+',%'
Where t(id int, list varchar(max)) is the table to search and #searchValue is the value you are looking for. If you need to search for more than one value you have to add those in a table and use a join or subquery.
E.g. if s(searchValue varchar(max)) is the table of values to search then:
SELECT distinct t.id, t.list
FROM t INNER JOIN s
ON ','+t.list+',' LIKE '%,'+s.searchValue+',%'
If you need to pass those search values from ADO.Net consider table parameters.

Performing query on two databases with stored procedure for returning two sets of data on dropdown

I have two drop downs on a form. Second drop down populates based on value selected on the first drop down. One of two stored procedures query I have basically displays data where the value for #LocID does not match selected on first dropdown does not exist and also performs subquery where no zipcodes are returned for anything matched with the declared #LocID.
DECLARE #LocID INT;
SELECT
DISTINCT l.[ZipCode],
[Description] = l.ZipCode + ' - ' + l.Description
FROM LocMap l
WHERE l.ZipCode NOT IN (
SELECT l2.ZipCode
FROM LocMap l2
WHERE l2.LocID = #LocID
);
Table named LocMap.
LocID | ZipCode | Description
----------------------------------
100 | 91012 | Magical Sky
100 | 91013 | Dream Land
101 | 91012 | Blue Ocean
102 | 91012 | Gray Screen
104 | 91014 | Limit Break
108 | 91016 | Magic Hammer
My problem is my second stored procedure that also returns data to this second dropdown labeled as Recently Added. It basically queries a table and returns all data for it (ZipCode + Description), no criteria or anything. What I would like to know is if it is possible to query two databases on the same server and if so, how exactly I would perform the same filtering of data I am doing on my stored procedure above with the stored procedure query for this second table. The first stored procedure has the #declare LocID, but this second one, all it does is return everything without anything being declared.
1) What would be the recommended way of doing this. Is it possible to get the results from first stored procedure and do a subquery similar to filter out my data with RecentlyAdded? Just like the first query, I don't want to return any zipcodes that match the LocID passed on this second table result as well.
Second stored procedure table named RecentlyAdded
ZipCode | Description
----------------------------------
91018 | Zelda
91019 | Sephiroth
91012 | Cloud
91012 | Aeris
91011 | Tifa
91010 | Barrett
Dropdown Layout Example
[Select LocID] (First Dropdown)
100
104
108
120
[Select ZipCode - Description] (Second Dropdown]
---Recently Added---
91010 - Barrett
91018 - Zelda
......................
......................
......................
---All other ZipCodes---
91016 - Magic Hammer
91014 - Limit Break
......................
......................
......................
You can do this in one fell swoop using the UNION operator:
DECLARE #LocID INT;
SELECT DISTINCT
f.[ZipCode],
[Description] = f.ZipCode + ' - ' + f.Description,
f.[RecentlyAdded]
FROM (
SELECT
l.[ZipCode],
l.[Description],
RecentlyAdded = CAST(0 AS BIT)
FROM LocMap l
UNION
SELECT
r.[ZipCode],
r.[Description],
RecentlyAdded = CAST(1 AS BIT)
FROM RecentlyAdded r
) f
WHERE f.ZipCode NOT IN (
SELECT l2.ZipCode
FROM LocMap l2
WHERE l2.LocID = #LocID
)
ORDER BY RecentlyAdded DESC;
After you get the input from both tables, you can store the result as its own "table" and do the filtering / selecting as if you were only querying the one table.
Make sure you change the database / schema name for RecentlyAdded above appropriately (didn't see it in the post).
SQL Fiddle
Use a temporary table to store the intermediate values as shown here. Depending on circumstances, either a true tamp table (as shown) or a table-valued variable might be appropriate.
create table #t(
ZipCode varchar(7)
,Description varchar(255)
);
-- N.B. Don't insert a **go** here
insert #t (ZipCode,Description)
exec <second stored procedure name and parameters>;
-- proceed to join to your prior query

Return multiple values in one column within a main query

I am trying to find Relative information from a table and return those results (along with other unrelated results) in one row as part of a larger query.
I already tried using this example, modified for my data.
How to return multiple values in one column (T-SQL)?
But I cannot get it to work. It will not pull any data (I am sure it is is user[me] error).
If I query the table directly using a TempTable, I can get the results correctly.
DECLARE #res NVARCHAR(100)
SET #res = ''
CREATE TABLE #tempResult ( item nvarchar(100) )
INSERT INTO #tempResult
SELECT Relation AS item
FROM tblNextOfKin
WHERE ID ='xxx' AND Address ='yyy'
ORDER BY Relation
SELECT #res = #res + item + ', ' from #tempResult
SELECT substring(#res,1,len(#res)-1) as Result
DROP TABLE #tempResult
Note the WHERE line above, xxx and yyy would vary based on the input criteria for the function. but since you cannot use TempTables in a function... I am stuck.
The relevant fields in the table I am trying to query are as follows.
tblNextOfKin
ID - varchar(12)
Name - varchar(60)
Relation - varchar(30)
Address - varchar(100)
I hope this makes enough sense... I saw on another post an expression that fits.
My SQL-fu is not so good.
Once I get a working function, I will place it into the main query for the SSIS package I am working on which is pulling data from many other tables.
I can provide more details if needed, but the site said to keep it simple, and I tried to do so.
Thanks !!!
Follow-up (because when I added a comment to the reponse below, I could not edit formatting)
I need to be able to get results from different columns.
ID Name Relation Address
1, Mike, SON, 100 Main St.
1, Sara, DAU, 100 Main St.
2, Tim , SON, 123 South St.
Both the first two people live at the same address, so if I query for ID='1' and Address='100 Main St.' I need the results to look something like...
"DAU, SON"
Mysql has GROUP_CONCAT
SELECT GROUP_CONCAT(Relation ORDER BY Relation SEPARATOR ', ') AS item
FROM tblNextOfKin
WHERE ID ='xxx' AND Address ='yyy'
You can do it for the whole table with
SELECT ID, Address, GROUP_CONCAT(Relation ORDER BY Relation SEPARATOR ', ') AS item
FROM tblNextOfKin
GROUP BY ID, Address
(assuming ID is not unique)
note: this is usually bad practice as an intermediate step, this is acceptable only as final formatting for presentation (otherwise you will end up ungrouping it which will be pain)
I think you need something like this (SQL Server):
SELECT stuff((select ',' +Relation
FROM tblNextOfKin a
WHERE ID ='xxx' AND Address ='yyy'
ORDER BY Relation
FOR XML path('')),1,1,'') AS res;