选择已选择所有子表行的父表行

时间:2016-07-20 07:17:58

标签: sql sql-server query-optimization

我有两个外键关系表。

Table1 (Parent Table)
  Id

Table2 (Child Table)
  Tbl2_Id
  Tbl1_Id (References Table1)
  OptionName
  OptonValue

样本数据:

Table1
_____________
  Id 
------------
  1
  2
  3


Table2
_____________
Tbl2_Id | Tbl1_Id | OptionName | OptionValue
--------------------------------------------
1       |  1      | Name       | John
2       |  1      | Surname    | Mach
3       |  1      | City       | Manhattan
4       |  2      | Nimi       | John
5       |  2      | City       | Manhattan
6       |  3      | CityOfBirth| Paris
...

Table2包含动态数据,因此它保留用户定义的键/值对。

我想使用此动态数据创建过滤机制。为此,用户将根据Table2定义过滤条件。当且仅当Table1中的所有子元素都使用Table2语句选中时,才会选择SELECT中的行。

,例如,

SELECT * from Table2 WHERE (OptionName = "Name" and OptionValue = "John" ) OR (OptionName = "Surname" and OptionValue = "Mach" ) OR (OptionName = "City" and OptionValue = "Manhattan")

假设给定SELECT返回4行。 3行有Tbl1_Id=1,1行有Tbl1_Id=2

Tbl_Id1 = 1返回了3行,总共有3行Tbl_Id1 = 1外键关系,因此为Table1中的第一条记录选择了所有子表行。 Tbl_Id1 = 2仅返回1行,但此关系在子表中总共有2条记录。没有为Tbl_Id1 = 3返回任何行 因此,我们必须返回Id=1Table1

我正在寻找一种方法来创建一个SELECT语句,该语句返回Table1中的所有记录都在子表table2

中选择的行

一种可能的方法是在Table2.Tbl1_Id上使用GROUP BY并计算分组记录,然后将此数字与类似的GROUP BY语句进行比较,该语句也有WHERE子句来选择拟合记录。返回相同数字的行意味着所有案例都被覆盖。

但这对DB来说是一个非常繁重的查询。在应用程序最常用的功能之一中需要逻辑。所以查询应该尽可能轻。

有没有办法让动态数据过滤更轻松?

编辑:示例数据已更改,示例查询已通过电子书编写

1 个答案:

答案 0 :(得分:1)

azure config set subscription {{MyIdSubscription}}

或者您可以使用GROUP BY as,

重写最后一个查询
-- store the result into temp table
SELECT Tbl2_Id, Tbl1_Id, OptionName, OptionValue
INTO #Resutl1
FROM Table2 WHERE (OptionName = 'Name' and OptionValue = 'John' ) OR .......

SELECT *
FROM #Result1

-- select master table data if all childs are selected..
SELECT *
FROM Table1 t1
WHERE 
    -- get Ids that are selectable.
    EXISTS( SELECT 1                
                FROM #Resutl1 r 
                WHERE r.Tbl1_Id = t1.Id
            )
    -- exclude those which do not have all entries selected.
    AND NOT EXISTS( SELECT 1
                    FROM Table2 t2
                    LEFT JOIN #Resutl1 r ON t2.Tbl2_Id = r.Tbl2_Id
                    WHERE t2.Tbl1_Id = t1.Id
                        AND r.Tbl2_Id IS NULL
            )