SQL 在表的两个副本之间留下了带有 WHERE 子句依赖关系的自连接
Posted
技术标签:
【中文标题】SQL 在表的两个副本之间留下了带有 WHERE 子句依赖关系的自连接【英文标题】:SQL left self-join with WHERE clause dependencies between the two copies of the table 【发布时间】:2012-05-07 06:41:12 【问题描述】:以下两句:
hello there
bye!
在表 sentence_words 中表示为:
WORD_ID SENTENCE_ID WORD WORD_NUMBER
10 1 hello 1
11 1 there 2
12 2 bye! 1
我想做一个外连接查询,给我结果:
WORD1 WORD2
hello there
bye! NULL
请注意,我可能想从句子中间开始,所以我不能假设 word2 的 word_number = 2。如果我选择 my_start_number = 2,那么查询应该给我:
WORD1 WORD2
there NULL
我试过了:
(my_start_number = 1)
select s1.word word1, s2.word word2
from sentence_words s1
left join sentence_words s2
on s1.sentence_id = s2.sentence_id
where s1.word_number = my_start_number
and (s2.word_number = s1.word_number +1 or s2.word_number is null);
如果句子中有两个单词,那只会给我一个结果。我不知道该怎么做这并不复杂。
【问题讨论】:
mssql、mysql、oracle都在用什么? 您是在尝试重新创建句子还是只是对返回的单词对感兴趣? 【参考方案1】:将word_number + 1
要求移至LEFT JOIN
。
SELECT
s1.word word1, s2.word word2
FROM
sentence_words s1
LEFT JOIN
sentence_words s2
ON s2.sentence_id = s1.sentence_id
AND s2.word_number = s1.word_number + 1
WHERE
s1.word_number = my_start_number
死灵编辑:
虽然上面修复了 LEFT JOIN 的使用,但我建议根本不要使用连接...
SELECT
sentence_id,
MAX(CASE WHEN pos = 0 THEN word END) AS word1,
MAX(CASE WHEN pos = 1 THEN word END) AS word2
FROM
(
SELECT
sentence_id,
word_number - MY_START_NUMBER AS pos,
word
FROM
sentence_words
)
AS offset_sentence_words
WHERE
pos IN (0, 1)
GROUP BY
sentence_id
【讨论】:
【参考方案2】:Dems 的答案绝对是正确的。我决定写这个答案来解释你原来的解决方案不起作用的原因。这是因为您正在尝试过滤左外连接的以下结果集(显示所有列,其中一些名称被缩写以适应):
s1.WORD_ID s1.SENT_ID s1.WORD s1.WORD_NUM s2.WORD_ID s2.SENT_ID s2.WORD s2.WORD_NUM
10 1 hello 1 10 1 hello 1
10 1 hello 1 11 1 there 2
11 1 there 2 10 1 hello 1
11 1 there 2 11 1 there 2
12 2 bye! 1 12 2 bye! 1
现在,看看你的 where 子句:
where s1.word_number = my_start_number
and (s2.word_number = s1.word_number +1 or s2.word_number is null);
...而且应该相对容易看出它为什么不起作用。例如,s2.word_number
永远不会是 NULL
。
【讨论】:
以上是关于SQL 在表的两个副本之间留下了带有 WHERE 子句依赖关系的自连接的主要内容,如果未能解决你的问题,请参考以下文章