栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用嵌套的IIF优化访问查询

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用嵌套的IIF优化访问查询

我假设您的代码包含错别字(无括号),并且实际上应该阅读:

WHERe IIf([GrpOrder]=3,IIf([LabelText]="Totals",True,False),True) = true

从SQL代码的角度来看,由于SQL具有以下三种值逻辑,实际上需要考虑九种情况

NULL

GrpOrder = 3GrpOrder <> 3GrpOrder IS NULLLabelText = 'Totals'LabelText <> 'Totals'LabelText IS NULL

总共有九种情况,例如测试数据和结果:

OP_result | GrpOrder | LabelText  ----------------------------------     TRUE |       55 | 'Totals'     TRUE |       55 | 'Tallies'     TRUE |       55 | <NULL>     TRUE |        3 | 'Totals'    FALSE |        3 | 'Tallies'    FALSE |        3 | <NULL>     TRUE |   <NULL> | 'Totals'     TRUE |   <NULL> | 'Tallies'     TRUE |   <NULL> | <NULL>

最安全的方法是写出一系列

OR
子句,
NULL
对每个
OR
子句的两列进行明示处理。但是,这很漫长,最好标记这两个返回FALSE的情况。这就是大多数人(包括我!)遇到NULL问题的地方:这太违反直觉了!

例如,写这个很诱人:

(GrpOrder = 3 AND LabelText IS NULL)OR(GrpOrder = 3 AND LabelText <> 'Totals')

然后使用

NOT
以下方法“翻转”其值:

NOT (     (GrpOrder = 3 AND LabelText IS NULL)     OR     (GrpOrder = 3 AND LabelText <> 'Totals')    )

但是,这样做会

NULL
潜入结果集中:

OP_result | attempt_1 | GrpOrder | LabelText  ---------------------------------------------     TRUE |      TRUE |       55 | 'Totals'     TRUE |      TRUE |       55 | 'Tallies'     TRUE |      TRUE |       55 | <NULL>     TRUE |      TRUE |        3 | 'Totals'    FALSE |     FALSE |        3 | 'Tallies'    FALSE |     FALSE |        3 | <NULL>     TRUE |      TRUE |   <NULL> | 'Totals'     TRUE |    <NULL> |   <NULL> | 'Tallies'     TRUE |    <NULL> |   <NULL> | <NULL>

因此,我们需要显式处理更多的情况,而不是乍一看。

我可以想到的最简单的谓词可以在Access中获得所需的结果:

NOT( (LabelText <> 'Totals' OR LabelText IS NULL) AND GrpOrder = 3  AND GrpOrder IS NOT NULL)

[…阅读起来很奇怪,我想知道OP的代码是否首先产生了期望的结果。]

要学习的主要课程:

  • 应该避免在SQL中使用NULL:这是违反直觉的,甚至由非常有经验的SQL编码人员也会导致错误。
  • 始终发布具有预期结果的架构(例如
    CREATE TABLE
    SQL DDL …)和示例数据(…例如
    INSERT INTO
    SQL DML …)(如果需要,则使用文字和图片;),因为如果您的列被标记为
    NOT NULL
    那么答案就非常简单!:)

@Yanir Kleiman评论:

GrpOrder不能同时为3和NULL,因此在这种情况下检查它是否不为null是多余的

可以这样认为是可以原谅的。但这就是Access
:)我们拥有声称符合SQL标准的SQL产品的出色规范。Access声称没有这种合规性,Access团队提供的文档的质量特别低。

相反,在Access-land中,要使某件事真实,您必须进行实际测试!

当我删除谓词时

AND GrpOrder IS NOT NULL

空将出现在结果集中。尽管感觉像“违背逻辑”,但请记住,SQL的三值逻辑仅在Access声明不符合的规范中定义。如果访问团队没有告诉我们该产品应该如何工作,那么我们如何确定以上内容是错误还是功能?即使我们可以说服他们这是一个错误,他们也会解决吗?

下面,我提供了VBA代码来重现此问题:只需将+复制粘贴到任何VBA模块中,无需设置引用。它在temp文件夹中创建一个新的.mdb,然后创建表和测试数据。Access不需要安装在计算机上,例如,使用Excel的VBA编辑器。

该消息框显示了分别包含和删除上述谓词时的结果集。除了两个表列之外,还有两个计算列显示为值-1(TRUE),0(FALSE)和NULL,最左边的是OP:

Sub AccessStrangeLogic()  On Error Resume Next  Kill Environ$("temp") & "DropMe.mdb"  On Error GoTo 0  Dim cat  Set cat = CreateObject("ADOX.Catalog")  With cat    .Create _        "Provider=Microsoft.Jet.OLEDB.4.0;" & _        "Data Source=" & _        Environ$("temp") & "DropMe.mdb"    With .ActiveConnection      Dim Sql As String      Sql = _      "CREATE TABLE GrpOrders" & vbCr & _      "(" & vbCr & _      " GrpOrder INTEGER," & vbCr & _      " LabelText NVARCHAr(10)" & vbCr & _      ");"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (55, 'Totals');"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (55, 'Tallies');"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (55, NULL);"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (3, 'Totals');"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (3, 'Tallies');"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (3, NULL);"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (NULL, 'Totals');"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (NULL, 'Tallies');"      .Execute Sql      Sql = _      "INSERT INTO GrpOrders (GrpOrder, LabelText)" & _      " VALUES (NULL, NULL);"      .Execute Sql      ' Include "AND GrpOrder IS NOT NULL"      Sql = _      "SELECT *, " & vbCr & _      "       IIf([GrpOrder]=3,IIf([LabelText]=""Totals"",True,False),True) = true AS OP_result, " & vbCr & _      "       NOT" & vbCr & _      "       (" & vbCr & _      "        (LabelText <> 'Totals' OR LabelText IS NULL)" & vbCr & _      "        AND GrpOrder = 3 " & vbCr & _      "        AND GrpOrder IS NOT NULL" & vbCr & "       )" & vbCr & _      "  FROM GrpOrders" & vbCr & _      " ORDER " & vbCr & _      "    BY GrpOrder DESC, LabelText DESC;"      Dim rs      Set rs = .Execute(Sql)      ' Remove "AND GrpOrder IS NOT NULL"      Sql = Replace$(Sql, "AND GrpOrder IS NOT NULL", "")      Dim rs2      Set rs2 = .Execute(Sql)      MsgBox _          "Include 'AND GrpOrder IS NOT NULL':" & vbCr & _          rs.GetString(, , vbTab, vbCr, "<NULL>") & vbCr & _          "remove 'AND GrpOrder IS NOT NULL':" & vbCr & _          rs2.GetString(, , vbTab, vbCr, "<NULL>")    End With    Set .ActiveConnection = Nothing  End WithEnd Sub


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/386305.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号