加入多个布尔值

时间:2009-07-17 22:43:36

标签: sql ms-access join

我有两个表,每个表有三个布尔(ms-access“是/否”)列。

表1:A1,B1,C1

表2:A2,B2,C2

我希望表2中的行给出表1中满足以下条件的特定行:

如果A1为真,则只有A2为真的行,如果A1为假,则为A2为真或假的行。 如果B1为真,则只有B2为真的行,如果B1为假,则为B2为真或假的行。 如果C1为真,则只有C2为真的行,如果C1为假,则为C2为真或假的行。

示例一

         A, B, C    
Table 1: 0, 1, 0  (selected row)

Table 2: 1, 0, 0
         0, 1, 0  (in return set)
         1, 1, 0  (in return set)
         0, 0, 1
         1, 0, 1
         0, 1, 1  (in return set)
         1, 1, 1  (in return set)

示例二

         A, B, C    
Table 1: 0, 0, 1  (selected row)

Table 2: 1, 0, 0
         0, 1, 0  
         1, 1, 0 
         0, 0, 1  (in return set)
         1, 0, 1  (in return set)
         0, 1, 1  (in return set)
         1, 1, 1  (in return set)

我怎样才能最好地完成这项工作?

例如,这不起作用:

SELECT        vw_fbScheduleFull.LocationName
            , vw_fbScheduleFull.FieldName
            , vw_fbScheduleFull.Description
            , vw_fbScheduleFull.StartTime
            , vw_fbScheduleFull.EndTime
            , vw_fbScheduleFull.LowerDivision
            , vw_fbScheduleFull.UpperDivision
            , vw_fbScheduleFull.SeniorDivision
FROM (vw_fbSchedule
      Full INNER JOIN fbDivision
         ON vw_fbScheduleFull.LowerDivision = fbDivision.LowerDivision
         AND fbDivision.LowerDivision = 1
         OR vw_fbScheduleFull.UpperDivision = fbDivision.UpperDivision
         AND fbDivision.UpperDivision = 1
         OR vw_fbScheduleFull.SeniorDivision = fbDivision.SeniorDivision   
         AND fbDivision.SeniorDivision = 1)
WHERE (vw_fbScheduleFull.PracticeDate = ?)
    AND (vw_fbScheduleFull.Locked IS NULL)
    AND (fbDivision.DivisionName = ?)
ORDER BY vw_fbScheduleFull.LocationName
       , vw_fbScheduleFull.FieldName
       , vw_fbScheduleFull.StartTime

2 个答案:

答案 0 :(得分:3)

这不是你问的SQL问题,只是一个布尔表达问题。我假设你在这些表中有另一列允许你加入t1到t2中的行,但是按照你的例子(t1中只有1行),你可以这样做:

  SELECT t2.A2
       , t2.B2
       , t3.C2
    FROM t1
       , t2
   WHERE (t2.A2 OR NOT T1.A1)
     AND (t2.B2 OR NOT T1.B1)
     AND (t2.C2 OR NOT T1.C1)
;

我现在看到你上面发布的非抽象答案。基于此,您的SQL中存在一些问题。首先,您应该只表达JOIN子句中与vw_fbScheduleFull表和fbDivision表相关的条件(即外键/主键关系);所有LowerDivision / UpperDivision / SeniorDivision东西都应该在WHERE子句中。

其次,您忽略了AND和OR运算符的运算符优先级 - 您希望将每个* Division对包含在parens中以避免不良影响。

不知道表的完整模式,我猜这个查询的正确版本看起来像这样:

  SELECT vw_fbScheduleFull.LocationName
       , vw_fbScheduleFull.FieldName
       , vw_fbScheduleFull.Description
       , vw_fbScheduleFull.StartTime
       , vw_fbScheduleFull.EndTime
       , vw_fbScheduleFull.LowerDivision
       , vw_fbScheduleFull.UpperDivision
       , vw_fbScheduleFull.SeniorDivision
    FROM vw_fbScheduleFull 
       , fbDivision
   WHERE vw_fbScheduleFull.PracticeDate = ?
     AND vw_fbScheduleFull.Locked IS NULL 
     AND fbDivision.DivisionName = ?
     AND (vw_fbScheduleFull.LowerDivision = 1 OR fbDivision.LowerDivision <> 1)
     AND (vw_fbScheduleFull.UpperDivision = 1 OR fbDivision.UpperDivision <> 1)
     AND (vw_fbScheduleFull.SeniorDivision = 1 OR fbDivision.SeniorDivision <> 1)
ORDER BY vw_fbScheduleFull.LocationName
       , vw_fbScheduleFull.FieldName
       , vw_fbScheduleFull.StartTime 
;

再看一次,我意识到你的“fbDivision.DivisionName =?”可能是将该表中的行数减少为1,并且这两个表之间没有正式的PK / FK关系。在这种情况下,您应该省略FROM子句中的INNER JOIN命名法,并列出两个表;我已经更新了我的例子。

答案 1 :(得分:0)

Steve Broberg的回答是正确和良好的;我只想补充说,别名可以使查询更容易:

SELECT f.LocationName
       , f.FieldName
       , f.Description
       , f.StartTime
       , f.EndTime
       , f.LowerDivision
       , f.UpperDivision
       , f.SeniorDivision
    FROM vw_fbScheduleFull f
       , fbDivision        d
   WHERE f.PracticeDate = ?
     AND f.Locked IS NULL 
     AND d.DivisionName = ?
     AND (f.LowerDivision = 1 OR d.LowerDivision <> 1)
     AND (f.UpperDivision = 1 OR d.UpperDivision <> 1)
     AND (f.SeniorDivision = 1 OR d.SeniorDivision <> 1)
ORDER BY f.LocationName
       , f.FieldName
       , f.StartTime 
;