Ceci est ma solution en utilisant les WINDOW functions
. J'ai utilisé le lag
et lead
les fonctions. Les deux renvoient une valeur d'une colonne d'une ligne en décalage par rapport à la ligne actuelle. lag
revient et lead
va ensuite dans le décalage.
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)
Version simplifiée :
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';
Points majeurs
= ANY()
n'est pas nécessaire, la fonction window renvoie une seule valeur- certains champs redondants dans la sous-requête
- pas besoin de trier par colonnes, que vous
PARTITION BY
- le ORDER BY s'applique dans partitions - N'utilisez pas d'identificateurs à casse mixte sans guillemets, cela ne ferait que prêter à confusion. (Mieux encore :n'utilisez pas d'identificateurs à casse mixte dans PostgreSQL jamais )