4

我目前有 2 个如下所示的 SQL 表:

数据表

和...

过滤表

我需要编写一个 SELECT 语句,从 DataTable 中检索包含与 FilterTable 匹配的行的所有产品。

因此,根据我上面的示例表,如果我要运行查询,它将返回以下结果:

结果表

我最近发现了一个尝试这样的问题: SQL query where ALL records in a join match a condition? 但未能成功实施类似的事情

注意 - 我使用的是 Microsoft SQL Server 2008

4

4 回答 4

16

这有点复杂,但这里有一个解决方案。基本上,您需要检查数据表中有多少记录与过滤表中的所有记录匹配。这使用子查询来做到这一点:

SELECT *
FROM DataTable
WHERE ID IN (
  SELECT DT.ID
  FROM DataTable DT
    JOIN FilterTable FT ON FT.Name = DT.Name 
          AND FT.Value = DT.VALUE
  GROUP BY DT.ID
  HAVING COUNT(*) = (SELECT COUNT(*) FROM FilterTable)
)  
于 2013-09-18T00:44:54.590 回答
2

这将起作用:

SELECT * FROM Data WHERE ID NOT IN (
    SELECT ID FROM Data JOIN Filter 
       on Data.Name = Filter.Name and Data.Value <> Filter.Value
)

如果您想尝试其他事情,我设置了一个 SQL Fiddle: http ://sqlfiddle.com/#!3/38b87/6

编辑:

更好的答案:

SELECT *
FROM DATA
WHERE ID NOT IN (
  SELECT ID
  FROM DATA
  JOIN Filter ON DATA.Name = Filter.Name
    AND DATA.Value <> Filter.Value
) AND ID IN
(
  SELECT ID 
  FROM DATA 
  JOIN Filter ON DATA.Name = Filter.Name
)

现在,这适合至少有一个匹配的过滤器,而没有一个不匹配的过滤器。

于 2013-09-18T00:53:22.430 回答
0

如果您可以使用 sp_executesql (您正在使用过程)。

SET NOCOUNT ON
GO

    CREATE TABLE Data  
    (
         [ID] INT
        ,[Name] VARCHAR(12)
        ,[Value] VARCHAR(2)
    )

    CREATE TABLE Filter  
    (
         [Name] VARCHAR(12)
        ,[Value] VARCHAR(2)
    )

    INSERT INTO Data ([ID], [Name], [Value])
    VALUES   (1, 'productname', 'A')
            ,(1, 'cost', '20')
            ,(1, 'active', 'Y')
            ,(2, 'productname', 'A')
            ,(2, 'cost', '20')
            ,(2, 'active', 'N')
            ,(3, 'productname', 'B')
            ,(3, 'cost', '20')
            ,(3, 'active', 'Y')
            ,(4, 'productname', 'A') 
            ,(4, 'cost', '20')
            ,(4, 'active', 'Y')

    INSERT INTO Filter ([Name], [Value])
    VALUES ('productname', 'A')
          ,('active', 'Y')

    DECLARE @SQLColumns NVARCHAR(MAX) = SUBSTRING((SELECT DISTINCT ',[' +[Name]  +']' FROM Data FOR XML PATH('')),2,4000)
    DECLARE @SQLFilterColumns NVARCHAR(MAX) = SUBSTRING((SELECT 'AND [' +[Name]  +'] = ''' + [Value] + ''' ' FROM Filter FOR XML PATH('')),4,4000)

    DECLARE @SQLStatement NVARCHAR(MAX) = N'
    ;WITH DataSource ([ID]) AS
    (
        SELECT [ID]
        FROM
        (
            SELECT [ID]
                  ,[Name]
                  ,[Value]
            FROM Data
        ) DataSource
        PIVOT
        (
            MAX([Value]) FOR [Name] IN (' + @SQLColumns+  ')
        ) PVT
        WHERE ' +  @SQLFilterColumns + '
    )
    SELECT DT.[ID]
          ,DT.[Name]
          ,DT.[Value]
    FROM Data DT
    INNER JOIN DataSource DS
        ON DT.[ID] = DS.[ID]
    '

    EXECUTE sp_executesql @SQLStatement

    DROP TABLE Data
    DROP TABLE Filter

SET NOCOUNT OFF
GO
于 2013-09-18T07:15:27.177 回答
0

这是使用几个 PIVOT 的选项

DECLARE @Data table ([ID] INT, [Name] VARCHAR(12), [Value] VARCHAR(2) )

DECLARE @Filter TABLE ( [Name] VARCHAR(12), [Value] VARCHAR(2)    )

    INSERT INTO @Data ([ID], [Name], [Value])
    VALUES   (1, 'productname', 'A')
            ,(1, 'cost', '20')
            ,(1, 'active', 'Y')
            ,(2, 'productname', 'A')
            ,(2, 'cost', '20')
            ,(2, 'active', 'N')
            ,(3, 'productname', 'B')
            ,(3, 'cost', '20')
            ,(3, 'active', 'Y')
            ,(4, 'productname', 'A') 
            ,(4, 'cost', '20')
            ,(4, 'active', 'Y')

    INSERT INTO @Filter ([Name], [Value])
    VALUES ('productname', 'A')
          ,('active', 'Y');

SELECT * 
FROM (  SELECT *
        FROM (select [ID], [Name], [value] from @Data) as s
        PIVOT 
        ( MAX([value]) FOR [name] in ( [productname], [active])
        ) as pvt) B
INNER JOIN 
        (   SELECT * 
        FROM (select [name], [value] from @Filter) as f
        PIVOT
        ( MAX([value]) for [Name] IN ([productname], [active]) 
        ) AS fpvt
    ) F 
ON F.active = b.active and f.productname = b.productname 

通过对 DATA 表然后对 FILTER 表执行 PIVOT,它允许它们排队以进行内部连接。这将返回两者中匹配的记录,

于 2015-12-04T14:07:49.820 回答