sql - 与表格列表相比,MS Access 从长文本字段中提取多个匹配的文本字符串
问题描述
问题:查询无法提取在长文本字段中找到的所有受限词。它从 ~100 个值的表列中获取受限制的单词。
样本数据
表:带有长文本字段的 RecipeTable:RecipeText
RecipeText 字段的示例内容:将大头菜、韭菜、胡萝卜和卷心菜添加到 Instant Pot®。密封并在高压下煮4分钟。快速释放蒸汽。将牛腩切成薄片穿过谷物,然后转移到盘子里。把蔬菜放在肉周围,撒上欧芹,配上酸奶油、辣根和芥末。
期望的结果: 想要将 RecipeText 字段与表中此短文本字段 RestrictedItem 中的每个值进行比较:RestrictedTable。
RestrictedTable.RestrictedItem 包含 100 个值。假设这个练习包含 6 个:牛奶、烘焙、勺子、胡萝卜、芥末和蒸汽。
查询将在单个记录中以无特定顺序查找这些匹配的单词:carrots mustard steam
结果:在长文本字段中仅找到许多匹配项中的一项。
期望结果:查找在长文本字符串中提取的所有匹配词。重复和通配符很好。区分大小写不好。
示例尝试:
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 & "*";
笔记:
- 我可以找到很多建议来查找单个单词,但不能将整个表格列与一个字段进行比较。
- 而且,有很多建议可以找到第一个子字符串或第 n 个位置,但我想要所有匹配的子字符串。不是位置,我担心应用修剪等会减慢搜索 100 个单词和修剪每个单词的速度。
- 我很好地将其作为我的表单上包含 RecipeText 字段的计算字段。
- 制作一个按钮来启动查询以将 RecipeText 字段与 RestrictedTable.RestrictedItem 列表进行比较并在同一表单上填写一个空字段 RestrictedFound 也很好。
解决方案
下面的代码是查找备注字段中所有受限单词的两种方法。虽然这一切都可以在没有暂存/工作表的情况下以编程方式完成,但我建议使用临时或永久表通过 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
那时,您可以进行计数、求和和其他数据。
对不起,我以为我有示例代码,但我找不到。很多个月前,我不得不在大学里使用 VBA 和 Access(字数统计/排名分配)做这样的事情,但我找不到。现在我会用带有数字表、XML/JSON 功能或全文搜索功能的 SQL Server 来做这种事情。
如果您需要限制在 MS Access 中的工作,希望这可以帮助您指明正确的方向。
如果您不习惯使用 ADODB 或 DAO 记录集,您可以使用外键和单词构建一个 CSV 分隔文件,然后将该文件导入工作表。
推荐阅读
- vbscript - 来自一个变量 VBScript 的多个文本文件
- node.js - NodeJS MongoDb updateMany() 有条件?
- javascript - 在 TAB 和/或 ENTER 上的 jQuery.autocomplete() 之后选择并将焦点移动到特定输入字段
- python - Python如何在列表推导中使用方法
- kubernetes - 在 Grafana 中创建自定义仪表板时出现问题(数据源是 Prometheus)
- elixir - 如何使用 AWS SNS 发送短信 usibng ExAws
- parsing - 一个值中有多个点的 SVG 路径数据
- python - 如何让 discord.py bot 添加 scorpius 符号以及 mod 角色?
- pandas - 打印和存储 t-test 循环的结果
- r - R data.frame colnames 取决于赋值运算符