Извлечение комбинации пункт-опция из БД - PullRequest
0 голосов
/ 02 марта 2012

У меня есть некоторая комбинация опциональных элементов в моем приложении, из которой пользователь может выбирать, и, следовательно, запрашивать SQL Server для получения некоторых результатов

Допустим, пользователь выбирает комбинацию, например:

Option1 - Item1
Option1 - Item2
Option2 - Item1

Таблица базы данных:

Option1     Item1     Details1    Details2    Details3
Option1     Item2     Details4    Details5    Details6
Option1     Item3     Details7    Details8    Details9
Option1     Item4     Details10   Details11   Details12
...
Option2     Item1     Details13   Details14   Details15

При выборе вышеупомянутой комбинации опций-элементов необходимо получить их соответствующие данные.

Как получить эти данные, передавв комбинации Option-Item в запросе?Я пробовал что-то вроде:

SELECT * FROM tbData 
  WHERE Strategy IN ('Option1','Option2') 
  AND Items IN ('Item1','Item2')

... но это дает неправильный ответ.

1 Ответ

0 голосов
/ 02 марта 2012

Вы не можете использовать IN таким образом. Вы должны сказать:

WHERE (Strategy = 'Option1' AND Items IN ('Item1', 'Item2'))
OR (Strategy = 'Option2' AND Items IN ('Item1'))

Это связано с тем, что IN для каждого столбца в отдельности означает «вернуть любые строки, в которых для стратегии задано любое значение (вариант 1 или вариант 2), а для элементов - любое значение (элемент 1 или элемент 2)». Вы не можете применить эти две концепции по отдельности и ожидать, что SQL Server будет знать, что Item2 применяется только к Option1.


Теперь еще один вариант - использовать табличный параметр. Таким образом, вы можете определить тип таблицы следующим образом в SQL Server:

CREATE TYPE dbo.Options AS TABLE
(
    Strategy VARCHAR(32),
    Items    VARCHAR(32)
);

Заполните DataTable в C # выбранными параметрами, затем передайте его. Ваш запрос становится:

CREATE PROCEDURE dbo.whatever
    @tvp dbo.Options READONLY
AS
BEGIN
    SELECT d.* FROM tbData AS d
      INNER JOIN @tvp AS t
      ON d.Strategy = t.Strategy
      AND d.Items = t.Items;
END
GO

РЕДАКТИРОВАТЬ добавив еще одну опцию.

Если вы можете передать набор опций в таблицу в виде строки с двумя разделителями, например,

@Options = 'Option1,Item1;Option1,Item2;Option2,Item1'

Тогда вы можете использовать табличную функцию, например,

CREATE FUNCTION dbo.SplitMultiStrings
(
    @List VARCHAR(MAX),
    @d1   CHAR(1),
    @d2   CHAR(1)
)
RETURNS TABLE
AS
  RETURN 
  (
    SELECT x, y FROM 
    (
      SELECT
        x = i.i.value('(./x/text())[1]', 'varchar(32)'),
        y = i.i.value('(./y/text())[1]', 'varchar(32)')
      FROM (
        SELECT [XML] = CONVERT(XML, '<i><x>' 
          + REPLACE(REPLACE(@List, @d1, '</x><y>'),
          @d2, '</y></i><i><x>') + '</y></i>')
      ) AS x CROSS APPLY [XML].nodes('i') AS i(i)
    ) AS y WHERE x IS NOT NULL AND y IS NOT NULL
  );
GO

Итак, теперь вы можете сказать:

CREATE PROCEDURE dbo.whatever
  @Options VARCHAR(MAX)
AS
BEGIN
  SET NOCOUNT ON;

  BEGIN TRY
    SELECT d.* 
      FROM dbo.SplitMultiStrings(@List, ',', ';') AS o
      INNER JOIN tbData AS d
      ON o.x = d.Strategy AND o.y = d.Items;
  END TRY
  BEGIN CATCH
    RAISERROR('You probably have a trailing ; or other formatting issue.', 11, 1);
  END CATCH
END
GO

И затем вызвать хранимую процедуру следующим образом (передав эту строку через запятую / точку с запятой из вашего приложения):

EXEC dbo.whatever @Options = 'Option1,Item1;Option1,Item2;Option2,Item1';

Но я все еще думаю, что вариант TVP - это путь.

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