2 votes

Comment puis-je trouver l'entrée de fin pour une entrée de début dans sql ?

Je suis tombé sur une table qui a une structure similaire à la variable @t ci-dessous.
Je veux trouver l'entrée finale pour chaque entrée de départ, mais cela devient difficile car les entrées peuvent contenir des sous-entrées.

Avez-vous une idée de la façon dont je pourrais trouver le EndEntryText pour le StartEntryText qui le parraine en utilisant sa position ?

Représentation visuelle des entrées :

-- Start 1
--  Start 2
--  Stop 2
--  Start 3
--      Start 4
--          Start 5
--          Stop 5
--      Stop 4
--  Stop 3
-- Stop 1   

Sortie souhaitée :

StartEntryText  EndEntryText
Start 1         Stop 1  
Start 2         Stop 2
Start 3         Stop 3
Start 4         Stop 4
Start 5         Stop 5

SQL :

-- Simplified Table Structure
DECLARE @t TABLE (EntryText varchar(16) NULL
    , EntryType varchar(16)
    , EntryIndex int NULL
)

-- Test Data
INSERT INTO @t(EntryText, EntryType, EntryIndex) 
SELECT d.EntryText
    , d.EntryType
    , d.EntryIndex
FROM 
(
    SELECT 'Start 1 ' AS EntryText, 1 AS EntryIndex, 'Open' AS EntryType
    UNION ALL SELECT 'Start 2' AS EntryText, 2 AS EntryIndex, 'Open' AS EntryType
    UNION ALL SELECT 'Stop 2' AS EntryText, 3 AS EntryIndex, 'Close' AS EntryType
    UNION ALL SELECT 'Start 3' AS EntryText, 4 AS EntryIndex, 'Open' AS EntryType
    UNION ALL SELECT 'Start 4' AS EntryText, 5 AS EntryIndex, 'Open' AS EntryType
    UNION ALL SELECT 'Start 5' AS EntryText, 6 AS EntryIndex, 'Open' AS EntryType
    UNION ALL SELECT 'Stop 5' AS EntryText, 7 AS EntryIndex, 'Close' AS EntryType
    UNION ALL SELECT 'Stop 4' AS EntryText, 8 AS EntryIndex, 'Close' AS EntryType
    UNION ALL SELECT 'Stop 3' AS EntryText, 9 AS EntryIndex, 'Close' AS EntryType
    UNION ALL SELECT 'Stop 1' AS EntryText, 10 AS EntryIndex, 'Close' AS EntryType
) d

-- TODO: Find EndEntryText
SELECT t.EntryText AS StartEntryText
    , NULL AS EndEntryText
FROM @t t
WHERE t.EntryType = 'Open'

1voto

Evaworcim Points 31

Ce n'est pas une solution parfaite mais cela devrait répondre à mes besoins.

Cela revient à calculer le niveau de chaque entrée en additionnant ses ancêtres +1 pour OPEN et -1 pour CLOSE . Puis obtient le premier CLOSE après chaque OPEN au même niveau.

-- Workout Indent level for each entry in the hierarchy
SELECT t.EntryText
    , t.EntryIndex
    , t.EntryType
    , r.Indent
INTO #t
FROM @t t
CROSS APPLY
(
    SELECT SUM(CASE WHEN s.EntryType = 'OPEN' THEN 1 ELSE -1 END)  
        + CASE WHEN t.EntryType = 'OPEN' THEN -1 ELSE 0 END AS Indent
    FROM @t s 
    WHERE s.EntryIndex <= t.EntryIndex
) r

-- Work out OPEN entry for CLOSE entry in the same level
SELECT tOpen.EntryText AS StartEntryText
    , t.EntryText AS EndEntryText
FROM #t t
OUTER APPLY   
(
    SELECT TOP(1) e.EntryText
        , e.EntryIndex
    FROM #t e
    WHERE e.EntryIndex < t.EntryIndex
        AND e.EntryType = 'OPEN'
        AND e.Indent = t.Indent
    ORDER BY e.EntryIndex DESC
) tOpen
WHERE t.EntryType = 'CLOSE'
ORDER BY tOpen.EntryIndex

DROP TABLE #t

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X