【问题标题】:MS Access Extract Multiple Matching Text Strings from Long Text Field compared to Table List与表格列表相比,MS Access 从长文本字段中提取多个匹配的文本字符串
【发布时间】:2019-07-26 11:31:58
【问题描述】:

问题:查询无法提取在长文本字段中找到的所有限制字词。它从 ~100 个值的表列中获取受限制的单词。

样本数据

表格:带有长文本字段的 RecipeTable:RecipeText

RecipeText 字段的示例内容:将大头菜、韭菜、胡萝卜和卷心菜添加到 Instant Pot®。密封并在高压下煮4分钟。快速释放蒸汽。将牛腩切成薄片穿过谷物,然后转移到盘子里。把蔬菜放在肉周围,撒上欧芹,配上酸奶油、辣根和芥末。

期望的结果: 想要将 RecipeText 字段与表中此短文本字段 RestrictedItem 中的每个值进行比较:RestrictedTable。

RestrictedTable.RestrictedItem 包含 100 个值。假设这个练习包含 6 个:牛奶、烘焙、勺子、胡萝卜、芥末和蒸汽。

查询将在单个记录中以无特定顺序查找这些匹配词:carrots mustard steam

我试过this:How to find words in a memo field with microsoft access

结果:仅在长文本字段的众多匹配项中找到 1 个

期望结果:查找从长文本字符串中提取的ALL匹配词。重复和通配符很好。区分大小写不好。

示例尝试:

SELECT a.Adjectives, b.Content
FROM A, B
WHERE b.Content Like "*" & a.[adjectives] & "*"

LIKE 和之后是我认为问题所在。我试过使用 %、括号、空格等都无济于事。

我的变成了这个:

SELECT RecipeTable.RecipeText, RestrictedTable.RestrictedItem
FROM RecipeTable, RestrictedTable
WHERE RecipeTable.RecipeText LIKE  "*" & RestrictedTable.RestrictedItem & "*";

注意事项:

  1. 我可以找到很多建议来查找单个单词,但不能将整个表列与一个字段进行比较。
  2. 还有很多关于找到第一个子字符串或第 n 个位置的建议,但我想要所有匹配的子字符串。不是位置,我担心应用修剪等会减慢搜索 100 个单词并为每个单词进行修剪的速度。
  3. 我可以在我的表单上将它作为一个计算字段来保存 RecipeText 字段。
  4. 也可以创建一个按钮,该按钮将启动一个查询,以将 RecipeText 字段与 RestrictedTable.RestrictedItem 列表进行比较,并在同一表单上填写一个空字段 RestrictedFound。

【问题讨论】:

  • Replace() 函数不区分大小写。 Replace("ABC","b","b") 将返回“AbC”。编辑问题以显示示例数据和所需结果。
  • 谢谢。我已经更新了我上面的问题。
  • 我尝试了您的查询匹配带有限制字词的食谱,它返回 3 条食谱记录,每个匹配的限制字词有 1 条记录。但是你想知道同一个词出现了多少次?为什么?目的是什么?
  • 您的解决方案是否返回 3 个“记录”?或者,它是在一条记录中返回 3 个找到的单词吗?后者是我想要实现的目标。
  • 还有另一种查看匹配词的方法 - 通过在字段中突出显示它们。我问了这个问题here。感谢您对两者提出建议。今晚我会试试你的想法!

标签: sql vba ms-access


【解决方案1】:

下面的代码是查找备注字段中所有受限单词的两种方法。虽然这一切都可以在没有暂存/工作表的情况下以编程方式完成,但我建议使用临时或永久表通过 VBA 中的拆分功能从备忘录字段中提取单词(在考虑标点符号和其他数据清理之后)。

将备注字段中的单词拆分为一个数组后,可以将它们插入到一个单独的表中,该表具有对 RecipeTable 的外键引用。如果需要,这可以是临时表或永久表,并且可以是工作流过程的一部分。可以将 PendingReview 之类的字段添加到 RecipeTable 以处理新记录,然后将其标记为 false,这样它们就不会被再次处理。

将单词添加到另一个表后,它可以连接到 RecipeTable 通过外键,你应该有限制词的所有匹配。

获得信息后,您可以存储统计信息并从临时表中丢弃工作记录或删除工作记录,直到流程再次运行。

您可以在 VBA 中使用受限单词的字典查找来完成所有操作,即查询受限单词表,添加到字典然后循环匹配备忘录字段中的每个单词,并进行小写或不区分大小写的比较,但它可能需要一段时间。

下面的第一个代码片段

(如果你想要编译时间检查,那么你必须参考 Microsoft Scripting Runtime 我的路径是 C:\Windows\SysWOW64\scrrun.dll)

Dim dic as Dictionary
Dim memoField as string
Dim words() as String
Dim matchCnt as Integer
'Other variables I didnt declare

'Code to populate dictionary
'Do Until rstRestricted.EOF
'  dic.add LCase$(rst("restrictedWord")), 0
'  rstRestricted.MoveNext
'Loop
'rstRestricted.Close
'Set rstRestricted = Nothing

Set rst = New adodb.Recordset
rst.Open "SELECT [MemoField] FROM RecipeTable;"
lngRowCnt = CLng(rst.RecordCount) - 1
For x = 0 to lngRowCnt
   memoField = LCase$(Nz(rst("MemoField")))
   'Replace punctuation like commas, periods
   'memoField = Replace(memoField, ",","")

   'Now split after data scrubbed
   words = Split(memoField, " ")
   intWordCnt = UBound(words)
   For z = 0 to intWordCnt
      If LenB(words(z)) <> 0 Then
          If dic.Exists(words(z) = True Then
              matchCnt = dic(words(z))
              dic(words(z)) = matchCnt + 1
          End If
      End If
   Next z
Next x

Dim WordKeys() as Variant
Dim y as Integer
Dim restrictedWord as string
Dim wordCnt as Integer

WordKeys = dic.Keys
For y = 0 to UBound(WordKeys) '-1
     restrictedWord = CStr(WordKeys(y))
     wordCnt = CInt(WordKeys(restrictedWord))
     'code to save or display stats
Next y

rst.Close
Set rst = Nothing
Set conn = Nothing

我只需将所有单词拆分到一个工作表中,并索引单词字段,然后对受限单词的计数进行聚合。

第二段代码

'Option Explicit 
Dim sql as String
Dim memoDelimitedData() as String
'Other variables declared

'Code to open Recordset table for recipe and also code to open 
'Work table with adOpenDynamic (SELECT * from WorkTable)

'loop through records to be processed
'Split Field (May need variant instead of array.  My Access VBA is rusty)
 words = Split(memoField, " ")
 intWordCnt = UBound(words)
 For x = 0 to intWordCnt
    With rstWorkTable
      .AddNew
      !Word = words(x)
      !ForeignKeyIdToRecipeTable = intForeignKeyId
      .Update
    End With
 Next x 

然后,当您添加了工作表记录后,您可以加入 RecipeTable 和 RestrictedTable。

因此,从备忘录字段构建一个分隔单词的工作表。将外键引用到配方表,然后通过 RestrictedItem 将 RestrictedTable 连接到 WorkTable。

如果需要,这可以是对生成表或临时表永久表的查询。等等

因此,这样的事情会为您提供受限表中任何单词的匹配项:

SELECT RecipeTable.RecipeText, RestrictedTable.RestrictedItem
FROM RecipeTable
  INNER JOIN WorkTable ON
   RecipeTable.Id = WorkTable.RecipeTableId
  INNER JOIN RestrictedTable ON
   WorkTable.ForeignKeyIdToRecipeTable = RestrictedTable.RestrictedItem

MS Access Split Function

此时您可以进行计数、求和和其他数据。

抱歉,我以为我有示例代码,但我找不到。很多个月前,我不得不在大学里使用 VBA 和 Access(字数统计/排名分配)做这样的事情,但我找不到。现在我会用带有数字表、XML/JSON 功能或全文搜索功能的 SQL Server 来做这种事情。

如果您需要限制在 MS Access 中的工作,希望这可以帮助您指明正确的方向。

如果您不习惯使用 ADODB 或 DAO 记录集,您可以使用外键和单词构建一个 CSV 分隔文件,然后将该文件导入工作表中。

【讨论】:

  • 谢谢。我已经编辑了我的问题。我不在乎对结果进行排名。我只想为单个记录获取多个找到的值。现在,查询每 1 条记录找到 1 个匹配项。我希望它找到每 1 条记录的所有匹配项。这可以是查询,也可以是输入到计算字段中的表达式。
  • Kim 我要去开会。我不小心按了 enter 而不是 shift enter。我已经编辑了答案,所以希望这个部分伪代码/真实代码是您正在寻找的。如果是我,我会将记录放在 SQL Server 中,利用 SQL Server 中的所有功能(本地或开发人员),然后链接到 Access 中的表,但我再次不知道您的限制。祝你好运。
  • 谢谢。我将不得不研究获取 SQL 服务器。
猜你喜欢
  • 2019-07-27
  • 2017-07-05
  • 2020-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多