Check if value is in different table - sql

so I am new to SQL and I have little experience with it. So please excuse if this is really basic but I can't seem to find it after googling...
so I have a table which contains a serialnumber field.
I have a single inputfield which contains comma seperated values with each one being a serialnumber. I just want to display the serialnumbers that are in that comma seperated string.
So I have a splitstring function that I can use which splits the string at the commas like this:
SELECT * FROM dbo.SplitString('sn1,sn2,sn3,sn4,sn5,sn6', ',')
this returns a table with each sn being a row.
So I would want something like this:
SELECT
*
FROM
tbl_serials AS sn
WHERE
sn.serialnumber in dbo.SplitString('sn1,sn2,sn3,sn4,sn5,sn6', ',')
so this would display only the rows where the serialnumber is inside the string. But I don't know how to syntactily construct this.
Any help is appreciated

One method to do this is using join:
SELECT sn.*
FROM tbl_serials sn JOIN
dbo.SplitString('sn1,sn2,sn3,sn4,sn5,sn6', ',') as ss(val)
ON sn.serialnumber = ss.val;
With your route, you need a subquery:
SELECT sn.*
FROM tbl_serials sn JOIN
WHERE sn.serialnumber in (SELECT val
FROM dbo.SplitString('sn1,sn2,sn3,sn4,sn5,sn6', ',') as ss(val)
);
In both these cases, the as ss(val) assigns a table alias and a column alias to the value. Some versions of SplitString might return more than one value (such as a position). If you have such a version, then you need to include the extra return values as named columns.

Related

filter ids by comma separated nvchar ids

imagine i have a simple table which contains Id (primary key) and Name rows.
Now i have a comma separated ids list like- 2,5,6. I just want to take these comma separated ids then get compare each of id with existing data. And return only those ids which is unique that's means not exists in database. Please note the output also should be same as like input format that's means comma separated format. I am using Microsoft SQL server 2017
What i already tried is like bellow:
select * from DemoTable where Id 2,5,6 not in DemoTable
But this seems not correct syntax. How can i fix it?
You may use this. You need to look from other side in this problem. I found it very interesting.
Actually you have a list of id's as base, and you want to exclude id from the string which are not in some table. So first we need to find the list of id's, after that we'll exclude them from the id's of table to get our desired result. At the end you may use stuff or string_agg to convert your final result into , separated string.
select Value from (
select value from string_split('1,2,3',',')) as t
where t.value not in (select id from demotable)
You may check this link for working fiddle.FIDDLE.
Here's your query.
select string_agg(val, ',') as result
from (
select value as val from string_split('1,2,3',',')) as t
where t.val not in (select id from tableA)
Result: (comma separated)
1,2,3

How to use a multi-element string for a IN sql query?

Is it possible to use the input from one field of the database for another query in combination with the IN statement. The point is that in the sting, I use for IN, contains several by comma separated values:
SELECT id, name
FROM refPlant
WHERE id IN (SELECT cover
FROM meta_characteristic
WHERE id = 2);
the string of the subquery is: 1735,1736,1737,1738,1739,1740,1741,1742,1743,1744
The query above give me only the first element of the string. But when I put the string directly in the query, I get all the ten elements:
SELECT id, name
FROM refPlant
WHERE id IN (735,1736,1737,1738,1739,1740,1741,1742,1743,1744);
Is it possible to have all ten elements and not only one with query like the first one.
My sql version is 10.1.16-MariaDB
You can use FIND_IN_SET in the join condition.
SELECT r.id, r.name
FROM refPlant r
JOIN (SELECT * FROM meta_characteristic m WHERE id=2) m
ON FIND_IN_SET(r.id,m.cover) > 0
If you use a sub-query as in the first code snippet you will get a filter for each row returned from it. It will not work when it returns as a single string field.
SELECT id, name
FROM refPlant
WHERE FIND_IN_SET(id, (SELECT cover
FROM meta_charateristic
WHERE id = 2));

SQL inner join list split for an SSRS report

I have a field that lists all language descriptions that a product has and the field can contain data like:
EN;FR;DE
It will always be a two letter language code followed by a semi colon.
I then have a stored procedure that looks for all products with a particular language code. Simply done by:
WHERE
ext.languages LIKE '%' + #language + '%'
The #language variable might just represent the letters EN for example. Now when I want to find a product that has both French and English languages on I need to pass in 'FR, EN' for the language variable. Now I have a custom function in SQL that splits the language variable into rows so I effectively have
Row 1-EN
Row 2-FR
Now I need to check my ext.language field to see if both those values exist.
I have attempted to do:
INNER JOIN MyFunctionsDatabase.dbo.listSplit(#language) as var1
ON ext.language LIKE '%'+var1.StringLiteral+'%'
This only brings back products where it contains either french or english I need it to bring back values where it contains both English and French.
Any advice would be greatly appreciated:
Try with below script, this i write for 3 language but can be done generic
Declare #Product AS Table(ProductID INT, [Language] Varchar(500))
Insert Into #Product Values(1,'EN;FR;DE'),(2,'EN'),(3,'EN;DE'),(4,'EN;FR')
SELECT * FROM
(
Select P.ProductID,L.Value
From #Product P
CROSS APPLY dbo.[udfSplit]([Language],';') L
) Product
PIVOT
(
Count(Value)
For Value in (EN,FR,DE)
)
AS PV
Where EN=1 AND FR=1
I'd be inclined to use a function that accepts a delimited string containing the language codes to check for and the string to check. It checks that each language code is in the string and returns false as soon as one of the desired languages isn't found. If everything is found it returns true.
Your sql would look like
select *
from mytable
where CheckHasAllLanguages(language, #languagesToCheck) = 1
I would make your parameter a multi-select and have each individual language be a selection. You could even feed the parameter with values from the database so it would automatically update if there is a new language. I'm going to call this parameter #LangMultiSelect
Since you only want items that items that match all of the selections you need to pass in a second parameter with the number of items that have been selected. In the properties of your dataset you can add another parameter that is set by an expression. Name it #LangCount and use the expression:
=Parameters!LangMultiSelect.Count
Then use a SQL query similar to this:
SELECT Name
FROM (
SELECT Name,
COUNT(*) OVER(PARTITION BY pt.id) AS lCount
FROM ProductTable AS pt
INNER JOIN MyFunctionsDatabase.dbo.listSplit(#language) AS var1 ON var1.id=pt.id
WHERE pt.language IN (#LangMultiSelect)
) AS t
WHERE t.lCount = #LangCount
That query uses the COUNT() aggregate as a window function to determine the number of matches the item has and then only returns results that match all of the selections in the multi-select parameter.
It works because I am splitting the count by a field that is the same for all of the item names that are the same item but in a different language. If you don't have a field like that this won't work.

Iterate through a list to get strings in SQL

I have a SQL table as shown below. I want to generate strings using the 2 fields in my table.
A B
M1 tiger
M1 cat
M1 dog
M3 lion
I want to read in this table, count the number of rows, and store it in string variables like String1 = M1_tiger, String2 = M1_cat, etc. What's the best way to do this?
You could do a concat type query.
SELECT (Table.A + '_' + Table.B) AS A_B, COUNT(*) AS RowsCount FROM Table
I'm asuming the your table name is "Table", the result where you will find the strings you want would be the column named A_B, each record will have two things in each record, one would be the string you asked for, the other column would always be the same thing, the total number of records on you table.
The count part is kinda easy but check this link so you can use the specific count you need: http://www.w3schools.com/sql/sql_func_count.asp
You can try this:
SELECT CONCAT(A, '_', B) FROM yourtable
When you say "read in this table", do you mean read it into a programming language like C#? Or do you want to dynamically create sql variables?
You may want to use a table variable to store your strings rather than individual variables. Regarding getting the row number, you could use something like:
WITH CTE AS
(
SELECT A, B,
ROW_NUMBER() OVER (order by OrderDate) AS 'RowNumber'
FROM MyTable
)
SELECT A,B,RowNumber FROM CTE
See this answer for more on how you may choose to use the table variable.
SQL: Dynamic Variable Names
If your are using Oracle, you can also do it like:
select A ||'_'||B
from yourTable
Solution for PostgreSQL
CREATE SEQUENCE one;
SELECT array_to_string(array_agg(concat('String',nextval('one'),' = ',A,'_',B)), ', ')
AS result
FROM test_table;
DROP SEQUENCE one;
Explanation:
Create a temporary sequence 'one' in order to use nextval function.
nextval('sequence') - advance sequence and return new value.
concat('input1', ...) - concatenate all arguments.
array_agg('input1', ...); - input values, including nulls,
concatenated into an array.
array_to_string('array', 'delimiter') - concatenates array elements
using supplied delimiter and optional null string.
Drop the sequence 'one'.
The output of the query (for two test rows in test_table):
result
-------------------------------------------
String1 = M1_tiger, String2 = M1_cat
(1 row)

MDX equivalent to LIKE

In SQL I like to search a column for matches of a particular string using something like this:
SELECT t.attributeNAME
FROM myTable t
WHERE t.attributeNAME LIKE '%searchString%'
I might like to use that in a temp table and then use the result in subsequent sections of a longer script like so:
--find the keys
SELECT t.attributeKEY
INTO #Temp
FROM myTable t
WHERE t.attributeNAMELIKE '%searchString%'
--use the keys
SELECT SUM(f.measure)
FROM myFacts f
INNER JOIN #Temp t ON
f.attributeKEY = t.attributeKEY
--use the keys again
SELECT SUM(F.measure)
FROM myOtherFacts F
INNER JOIN #Temp t ON
F.attributeKEY = t.attributeKEY
Is there an equivalent to this in MDX? If I have an idea what items from a hierarchy that I'm after can I somehow use a searchString to filter to a specific set of items?
EDIT
As pointed out by Marc Polizzi answer it seems like instr is very useful in this situation and I can do the following:
CREATE SET [xCube].[Set_Names] AS
{FILTER(
[xDimension].[xHierarchy].[xLevel].Members,
(InStr(1, [xDimension].[xHierarchy].CurrentMember.NAME, "WIL") <> 0)
)
}
GO
SELECT
NON EMPTY
[Set_Names]
ON ROWS,
NON EMPTY
[Measures].[x]
ON COLUMNS
FROM [xCube]
GO
SELECT
NON EMPTY
[Set_Names]
ON ROWS,
NON EMPTY
[Measures].[y]
ON COLUMNS
FROM [xCube]
GO
SELECT
NON EMPTY
[Set_Names]
ON ROWS,
NON EMPTY
[Measures].[z]
ON COLUMNS
FROM [xCube]
You might be able to use the Instr function even if it does not support wildcard.
There is no such thing like like in plain MDX, but there is an implementation in the ASSP project: http://asstoredprocedures.codeplex.com/wikipage?title=StringFilters&referringTitle=Home