我想知道如何在SQL查询中检索结果,与下一行或上一行进行一些逻辑比较。我正在使用PostgreSQL。
示例
假设我的数据库中有一个表有两个属性(有序位置和随机数),我想检索偶数之间的奇数。我怎么能这样做?
真实用途
我想找到两个具有NAME类别的单词之间的单词(而单词不是名称)。订购由句子和位置提供。
修改 我想知道PostgreSQL的Window函数是否是解决这类问题的最佳解决方案。我听说过它们,但从未使用过。
答案 0 :(得分:39)
这是我使用WINDOW functions
的解决方案。我使用了lag
和lead
函数。两者都从与当前行偏移的行中的列返回值。 lag
返回,lead
在偏移中接下来。
SELECT tokcat.text
FROM (
SELECT text, category, chartype, lag(category,1) OVER w as previousCategory, lead(category,1) OVER w as nextCategory
FROM token t, textBlockHasToken tb
WHERE tb.tokenId = t.id
WINDOW w AS (
PARTITION BY textBlockId, sentence
ORDER BY textBlockId, sentence, position
)
) tokcat
WHERE 'NAME' = ANY(previousCategory)
AND 'NAME' = ANY(nextCategory)
AND 'NAME' <> ANY(category)
简化版:
SELECT text
FROM (
SELECT text
,category
,lag(category) OVER w as previous_cat
,lead(category) OVER w as next_cat
FROM token t
JOIN textblockhastoken tb ON tb.tokenid = t.id
WINDOW w AS (PARTITION BY textblockid, sentence ORDER BY position)
) tokcat
WHERE category <> 'NAME'
AND previous_cat = 'NAME'
AND next_cat = 'NAME';
= ANY()
PARTITION BY
- ORDER BY在分区中应用 答案 1 :(得分:5)
您可以在此地址找到最佳解决方案:
SQL Server 2012及更高版本的查询1:
square
SQL Server 2005+及更高版本的查询2:
SELECT
LAG(p.FirstName) OVER(ORDER BY p.BusinessEntityID) PreviousValue,
p.FirstName,
LEAD(p.FirstName) OVER(ORDER BY p.BusinessEntityID) NextValue
FROM Person.Person p
GO
答案 2 :(得分:2)
这应该有效:
SELECT w1.word AS word_before, w.word, w2.word AS word_after
FROM word w
JOIN word w1 USING (sentence)
JOIN word w2 USING (sentence)
WHERE w.category <> 'name'
AND w1.pos = (w.pos - 1)
AND w1.category = 'name'
AND w2.pos = (w.pos + 1)
AND w2.category = 'name'
IS NOT NULL
要回答你的其他问题:不,在这种情况下,窗口函数不是特别有用,自我加入是这里的神奇词。
编辑:
我纠正了。 Renato使用窗口函数lag() and lead()演示了一个很酷的解决方案
请注意细微差别:
pos -1
的行,则pos
的行不符合条件。lag()
和lead()
的Renatos版本对ORDER BY
创建的行的相对位置进行操作。在许多情况下(可能在手头的那个?)两个版本都会产生相同的结果。由于id空间存在差异,因此会有不同的结果。