Справка по поисковому запросу sql с использованием параметра с разделителями-запятыми - PullRequest
0 голосов
/ 25 марта 2011

Я ищу что-то подобное, но не могу найти лучший способ написать запрос:

SELECT DISTINCT CategoryID FROM tbl_Categories c INNER JOIN 
  mappingTable mp ON c.CategoryID = mp.CategoryID INNER JOIN
  SubCategories sc ON mp.SubCategoryID = sc.SubCategoryID
WHERE sc.SubcategoryID IN ALL (234,245,645)

В настоящее время я создаю динамический запрос, поскольку идентификаторы передаются в виде запятойСтрока '234,245,645' Но, как мы все знаем, нет такой вещи, как ВСЕ.В основном я хочу вернуть все категории, которые имеют все подкатегории в списке.Надеюсь, это имеет смысл.

Ответы [ 6 ]

3 голосов
/ 25 марта 2011

вы можете сделать это:

РЕШЕНИЕ 1

SELECT CategoryID
FROM tbl_Categories c INNER JOIN 
  mappingTable mp ON c.CategoryID = mp.CategoryID INNER JOIN
  SubCategories sc ON mp.SubCategoryID = sc.SubCategoryID
WHERE sc.SubcategoryID IN (234,245,645)
GROUP BY CategoryID
HAVING COUNT(sc.SubcategoryID)
       = LEN(
          REPLACE(
           REPLACE(
            REPLACE(
             REPLACE(
              REPLACE(
               REPLACE(
                REPLACE(
                 REPLACE(
                  REPLACE(
                   REPLACE(
                    REPLACE('234,245,645','0','')
                   , '1', '')
                  , '2', '')
                 , '3', '')
                , '4', '')
               , '5', '')
              , '6', '')
             , '7', '')
            , '8', '')
           , '9', '')
          , ' ', '')) + 1

РЕШЕНИЕ 2: еще один, который может работать:

SELECT CategoryID
FROM tbl_Categories c INNER JOIN 
  mappingTable mp ON c.CategoryID = mp.CategoryID INNER JOIN
  SubCategories sc ON mp.SubCategoryID = sc.SubCategoryID
WHERE sc.SubcategoryID IN (234,245,645)
GROUP BY CategoryID
HAVING COUNT(sc.SubcategoryID) 
       = (SELECT COUNT(DISTINCT SubcategoryID)
            FROM SubCategories 
           WHERE SubcategoryID IN (234,245,645))
1 голос
/ 25 марта 2011

Создайте функцию разделения, чтобы преобразовать CSV в табличное значение, затем присоедините функцию табличного значения к предложению select, чтобы ограничить результаты. Смотри http://phelabaum.com/archive/tag/tally-table/

Быстрый пример (требуется создать таблицу подсчета, как подробно описано здесь http://www.sqlservercentral.com/articles/T-SQL/62867/):

CREATE FUNCTION [dbo].[TallySplit] (@Delim CHAR(1), @String VARCHAR(8000))
    RETURNS TABLE AS 
    RETURN (
    SELECT SUBSTRING(@Delim + @String + @Delim,N+1,CHARINDEX(@Delim,@Delim + @String + @Delim,N+1)-N-1) ListValue
    FROM Tally
    WHERE N < LEN(@Delim + @String + @Delim)
    AND SUBSTRING(@Delim + @String + @Delim,N,1) = @Delim 
    )
GO

Затем напишите ваш выбор так:

DECLARE @vCatIDs varchar(max)
SET @vCatIDs = '234,245,645'
SELECT DISTINCT CategoryID FROM tbl_Categories c 
  INNER JOIN mappingTable mp ON c.CategoryID = mp.CategoryID 
  INNER JOIN SubCategories sc ON mp.SubCategoryID = sc.SubCategoryID
  INNER JOIN dbo.TallySplit(',',@vCatIDs) ts ON ts.ListValue = sc.SubCategoryID
1 голос
/ 25 марта 2011

Вы можете написать свою собственную функцию разделения:

CREATE FUNCTION [dbo].[Split]
(
    @ItemList NVARCHAR(MAX), 
    @delimiter CHAR(1)
)
RETURNS @IDTable TABLE (Item VARCHAR(50))  
AS      

BEGIN    
    DECLARE @tempItemList NVARCHAR(MAX)
    SET @tempItemList = @ItemList

    DECLARE @i INT    
    DECLARE @Item NVARCHAR(4000)

    SET @tempItemList = REPLACE (@tempItemList, ' ', '')
    SET @i = CHARINDEX(@delimiter, @tempItemList)

    WHILE (LEN(@tempItemList) > 0)
    BEGIN
        IF @i = 0
            SET @Item = @tempItemList
        ELSE
            SET @Item = LEFT(@tempItemList, @i - 1)
        INSERT INTO @IDTable(Item) VALUES(@Item)
        IF @i = 0
            SET @tempItemList = ''
        ELSE
            SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - @i)
        SET @i = CHARINDEX(@delimiter, @tempItemList)
    END 
    RETURN
END  

Затем вы можете присоединиться или выбрать таблицу, которая возвращается из этой пользовательской функции с табличным значением.

0 голосов
/ 25 марта 2011
DECLARE @Delimitedtext varchar(max);
DECLARE @Delimiter char(1);
SET @Delimitedtext = '234,245,645,';
SET @Delimiter = ',';

;WITH Strings(s, r)
AS
(
SELECT
SUBSTRING(@Delimitedtext,1, CHARINDEX(@Delimiter, @Delimitedtext)-1) s,
SUBSTRING(@Delimitedtext,CHARINDEX(@Delimiter, @Delimitedtext)+1, len(@Delimitedtext)) r
UNION ALL
SELECT
SUBSTRING(r,1, CHARINDEX(@Delimiter, r)-1) s,
SUBSTRING(r,CHARINDEX(@Delimiter, r)+1, len(r)) r
FROM Strings
WHERE
CHARINDEX(@Delimiter, r) > 0
)

SELECT  CategoryId
FROM    (
            SELECT  c.CategoryID
            FROM    tbl_Categories c 
            JOIN    mappingTable mp 
                ON  c.CategoryID = mp.CategoryID 
            JOIN    SubCategories sc 
                ON  mp.SubCategoryID = sc.SubCategoryID
            WHERE   sc.SubcategoryID IN (SELECT s FROM Strings)
        ) x
GROUP BY CategoryId
HAVING COUNT(*) = (SELECT count(*) FROM Strings)

Разделенная на строки копия из здесь .Обратите внимание, что вам нужен завершающий символ ','.

. Другие реализации разбиения строк могут быть лучше для вас, но это показывает, как обрабатывать условие 'ALL'.

0 голосов
/ 25 марта 2011
-- Parameter string
declare @ParamStr varchar(100) = '234,245,645'

-- Convert param to xml
declare @XMLStr xml = convert(xml, '<r>'+replace(@ParamStr, ',', '</r><r>')+'</r>')

-- Store param values in table variable
declare @T table (ID int)
insert into @T 
select r.value('.', 'int')
from @XMLStr.nodes('r') r(r)

-- Get the number of parameters
declare @ParamCount int = (select count(*) from @T)

-- Get the categoryids
select CategoryID
from mappingTable
where SubCategoryID in (select id from @T)
group by CategoryID
having count(CategoryID) = @ParamCount
0 голосов
/ 25 марта 2011

Не уверен, действительно ли это то, что вы хотите, поскольку ваш вопрос немного неясен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...