我有一个每行一个单词的表格和一个连续有一些文本的表格。我只需要从第二个表中选择那些不包含第一个表中单词的行。
例如:
带有约束词的表
约束字 |
---|
例子 |
苹果 |
橘子 |
蘑菇 |
车 |
qwerty |
带文字的表格
文本 |
---|
词 1。苹果;word3,例子 |
word1,苹果,word2。车 |
word1 word2橙色word3 |
蘑菇word1 word2 word3 |
word1车 |
qwerty |
在这种情况下不应选择任何内容,因为第二个表中的每一行都包含第一个表中的单词。
我只有一个想法CROSS JOIN
来实作这一目标
SELECT DISTINCT text FROM text_table CROSS JOIN words_table
WHERE CONTAINS(text, constraint_word ) = 0
有没有办法在不使用的情况下做到这一点CROSS JOIN
?
uj5u.com热心网友回复:
contains
指 Oracle 文本;交叉连接意味着笛卡尔积(通常是性能噩梦)。
避免这两种情况的一个选项是instr
函式(检查 in 的存在constraint_word
,text
但这次使用内部连接)和minus
集合运算子。
像这样,使用您发布的示例资料:
SQL> select * from text_table;
TEXT
---------------------------
word1.apple; word3, example
word1, apple, word2.car
word1 word2 orange word3
mushroomword1 word2 word3
word1 car
qwerty
6 rows selected.
SQL> select * From words_table;
CONSTRAI
--------
example
apple
orange
mushroom
car
qwerty
6 rows selected.
SQL>
正如您所说,最初查询不应回传任何内容,因为所有内容都constraint_words
存在于text
:
SQL> select c.text
2 from text_table c
3 minus
4 select b.text
5 from words_table a join text_table b on instr(b.text, a.constraint_word) > 0;
no rows selected
让我们修改其中text
一行:
SQL> update text_table set text = 'xxx' where text = 'qwerty';
1 row updated.
现在结果如何?
SQL> select c.text
2 from text_table c
3 minus
4 select b.text
5 from words_table a join text_table b on instr(b.text, a.constraint_word) > 0;
TEXT
---------------------------
xxx
SQL>
对; 我们刚刚修改的文本。
uj5u.com热心网友回复:
您的想法很好,因为您需要测验每个文本的所有单词。这就是 CROSS JOIN 所做的 - 组合(笛卡尔积)。
我们甚至可以更严格地获得更好的性能并使用 INNER JOIN 或简写JOIN
。
另请参阅:SQL 中的 CROSS JOIN 与 INNER JOIN
此外,您需要过滤所有text
没有匹配项的记录。这意味着每个组合中不匹配的计数text
是最大值(= 约束字数,此处为 6)。这个过滤器可以使用GROUP BY
WITHHAVING
-- text without any constaint_word
SELECT t.text, count(*)
FROM text_table t
JOIN words_table w ON CONTAINS(t.text, w.constraint_word, 1) = 0
GROUP BY t.text
HAVING count(*) = (SELECT count(*) FROM words_table)
;
它将输出:
文本 | 数数(*) |
---|---|
蘑菇word1 word2 word3 | 6 |
在SQL Fiddle上尝试演示
整个单词与部分匹配
请注意,约束词中的“蘑菇”不匹配,CONTAINS
因为它包含为词部分而不是整个词。
对于部分匹配,您可以使用LittlefootINSTR
的回答。
也可以看看
- 在 oracle SQL 查询中使用字符串包含函式
- PL-SQL 中的 contains() 是如何作业的?
- Oracle 背景关系索引
- 创建和维护 Oracle 文本索引
uj5u.com热心网友回复:
我相信这行得通(我认为CROSS JOIN
路线的问题在于它包含任何不包含至少一个单词的文本——不仅仅是不包含任何单词的文本):
SELECT DISTINCT text FROM text_table WHERE (SELECT COUNT(*) FROM words_table WHERE CONTAINS(text, constraint_word)) = 0;
0 评论