从DB中检索选项项组合

时间:2012-03-01 23:34:10

标签: sql sql-server-2008 stored-procedures

我的应用程序中有一些选项组合,用户可以从中进行选择,因此可以从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 :(得分:0)

你不能那样使用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)
);

使用所选选项在C#中填充DataTable,然后将其传入。您的查询变为:

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选项是要走的路。