简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM