加入多个布尔值
Posted
技术标签:
【中文标题】加入多个布尔值【英文标题】:Join on multiple booleans 【发布时间】:2009-07-17 22:43:36 【问题描述】:我有两个表,每个表都有三个布尔(ms-access“是/否”)列。
表 1:A1、B1、C1
表 2:A2、B2、C2
如果表 1 中的特定行满足以下条件,我想要表 2 中的行:
如果 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
【问题讨论】:
那应该是下一个相关网站。 domyhomework.com 不,这是真的。我没有作业。抱歉简化了示例。 @onedaywhen:您的评论令人困惑。您似乎的意思是布尔字段应该是 NULLable 并且 Yes/No 字段的 Jet/ACE 实现不是(这是真的)。但是您的第二句话似乎说 Yes/No is Nullable。 Access 数据库引擎的 YESNO 数据类型不是布尔值。 YESNO 不可能是因为,像所有 SQL 数据类型一样,它是 NULLable 即三值逻辑。因此,因为 YESNO 可以有三个值,所以它不是布尔值。另外,我听说 YESNO 数据类型在 NULLability (allenbrowne.com/NoYesNo.html) 方面有问题,所以我建议避免使用它,而不是 example_yesno INTEGER DEFAULT 0 NOT NULL, CHECK (example_yesno IN (0, 1) ) 【参考方案1】:您要问的并不是真正的 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 对括在括号内以避免不良影响。
不知道表的完整架构,我猜这个查询的正确版本应该是这样的:
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 = ?”可能正在将该表中的行数减少到一,并且这两个表之间没有正式的 PK/FK 关系。在这种情况下,您应该放弃 FROM 子句中的 INNER JOIN 命名法,只列出两个表;我已经更新了我的示例。
【讨论】:
+ 1 表示简化的 where 子句。 在我使用“OR NOT”语法创建查询后,它看起来正在工作。我的 IDE(Visual Studio Express)经常重新组织我的 SQL,包括清除括号(如本例所示),或者更经常添加一大堆不需要的括号。我尝试了许多非 JOIN 方法来实现此过滤,但不知何故说服自己需要 JOIN。感谢您的帮助。【参考方案2】: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
;
【讨论】:
这个答案来自可能不使用 Access,但手动编写 SQL 的人。 在这两个方面都正确。 Access 的 SQL 不包含别名吗?以上是关于加入多个布尔值的主要内容,如果未能解决你的问题,请参考以下文章