Access中的IIF语句破坏层次结构中稍后值的重叠

时间:2016-01-24 10:37:58

标签: sql excel vba ms-access iif

我正在提炼一个早先的问题,试图在这里问一些有形的东西。为了解决问题,我有一个有点大的数据集(大约250k行),我需要根据在字段中是否找到某个文本字符串,将给定的连接字段转换为每个行项目的输出。这已经在Excel中进行过管理(使用IF(IFERROR(FIND())),但公式对Excel过于繁琐,我需要将整个过程移动到Access以更好地自动化它。最终目标是生成单个可以粘贴到Excel模型中的表,然后刷新修订日期。

现有SQL:

SELECT my_field_1 ,
my_field_2,
my_field_3,
IIF(Active = 'Yes' AND Issue IS NULL,'OK',
IIF(Issue LIKE '123','123',
IIF(Issue LIKE'234','234',
IIF(Issue LIKE '345','345',

//* Etc going down to 14 nested IIF statements in the above format and 
//* returning NULL where conditions are not met. I then roll up the 3 issue
//* sets as follows

IIF(IssueSet1 IS NOT NULL, IssueSet1,
IIF(IssueSet2 IS NOT NULL, IssueSet2,
IIF(IssueSet3 IS NOT NULL, IssueSet3,
'Check for errors')))

期望的输出

',123,234'应在成功的查询输出中返回'123'到列RollUp。

现在的层次结构被分成2组14个嵌套的IIF语句,采用上述格式,第3组包含4个嵌套的IIF语句。然后,我将如上所述汇总所有IIF语句。不幸的是,Access正在返回ca. 20k NULL项目,其中较早的IIF在同一行上的后续IIF之前被触发,例如, 1行满足2个IIF的条件,这是不可避免的,因为我需要使用这个层次结构来“优先化”层次结构中更紧迫的问题。

问题:

  • 如果层次结构首先触发'123',然后'234'跟在同一个行项目上,它返回NULL而不是返回123.有什么方法可以让它停止发生所以任何进一步的层次结构胜过它下面的任何东西?如果我可以在除Access之外的平台上执行此操作,这在CASE语句中可以正常工作,这非常令人沮丧。

  • 现有的格式很笨重,我更喜欢使用查阅列和永久表但我无法弄清楚如何只返回我需要的值(例如'123')而不是整个字段(例如”,123234345456' )

  • 我需要最终生成一个摘要输出,可以轻松地复制并粘贴到相当的Excel模型中(或通过VBA自动输入) 问题ID(已生成IIF),类别(已存在),子类别(已存在),计数(按问题ID,类别和子类别分组的总和,如果我对此IIF问题进行排序,我可以自行完成)。

非常感谢,我希望这能澄清我想要做的事情。

Ĵ

1 个答案:

答案 0 :(得分:2)

Issue LIKE '123'相当于Issue = '123',因为该模式不包含任何wildcards

如果您想说"其中Issue包含'123',"这将是Issue LIKE '*123*' 但是,您必须确保不会意外地指定更长可能值的子字符串。例如。如果Issue中的值列表包含'...,987123,...',您可能不希望匹配123,但它会匹配。

最好的方法是将Issue解析成某种数组并查看它是否包含值。例如。通过编写VBA函数并在查询中使用它:

Option Compare Database

Public Function ContainsInList(ByVal CommaSeparatedList As Variant, ByVal Value As Variant) As Boolean
  If IsNull(CommaSeparatedList) Then Exit Function
  If IsEmpty(CommaSeparatedList) Then Exit Function
  If IsNull(Value) Then Exit Function
  If IsEmpty(Value) Then Exit Function
  If Len(CommaSeparatedList) = 0 Then Exit Function
  If Len(Value) = 0 Then Exit Function

  ContainsInList = InArray(Split(CommaSeparatedList, ","), Value)
End Function

Public Function InArray(ByRef Arr As Variant, ByVal Value As Variant) As Boolean
  Dim i As Long

  For i = LBound(Arr) To UBound(Arr)
    If Arr(i) = Value Then
      InArray = True
      Exit Function
    End If
  Next
End Function
SELECT
  IIF(Active = 'Yes' AND Issue IS NULL,'OK',
  IIF(ContainsInList(Issue, '123'), '123',
  IIF(ContainsInList(Issue, '234'), '234', ... 

此时为123创建查找表并不困难,例如:

priority int not null,
value varchar(50) not null

并使用它代替嵌套的IF:

SELECT
  IIF(Active = 'Yes' AND Issue IS NULL, 'OK',
  NZ((select top 1 [123s].value from [123s] where ContainsInList(Issue, [123s].value) order by [123s].priority), Issue))