2015-12-14 6 views
5

(questa è la mia prima domanda di overflow dello stack. Quindi, fatemi sapere i suggerimenti per porre una domanda migliore, se non capisco.) Ho una tabella di circa 500 persone (utenti) che stanno salendo le scale dal pavimento x (0 = x, max (y) = 50). Una persona può scalare zero/uno o più livelli in un singolo go che corrisponde a una singola riga del tavolo insieme al tempo necessario per farlo in pochi secondi. Voglio trovare il tempo medio impiegato per andare dal piano a al + 1 dove a è qualsiasi numero del piano. Per farlo intendo suddividere ogni riga della tabella menzionata in righe che hanno start_level + 1 = end_level. La durata sarà divisa in parti uguali come mostrato nella TABELLA DELLE OUTPUT PREVISTE per l'utente b.ms che aggiunge righe ogni qualvolta il livello cambia di più di 1 in modo che ogni riga abbia differenza di 1 in start_level e end_level

GIVEN TABLE INPUT 
start_level end_level duration user 
1   1   10  a 
1   2   5   a 
2   5   27  b 
5   6   3   c 

EXPECTED OUTPUT 

start_level end_level duration user 
1   1   10  a 
1   2   5  a 
2   3   27/3  b 
3   4   27/3  b 
4   5   27/3  b 
5   6   3  c 

Nota: i salti di livello sono solo in numeri interi. Dopo aver ottenuto l'output previsto, posso semplicemente creare una colonna sum (duration)/count (utenti distinti) a un livello start_level per ottenere il tempo medio necessario per ottenere un piano sopra da ogni piano.

Qualsiasi aiuto è apprezzato.

+0

Cosa hai fatto fino ad ora? Qual è esattamente la tua domanda? – Shadow

+0

come si raggiunge il valore di end_level? Nei dati di test end_level è 5 quando start level è 2, al risultato atteso end_level è 3 quando start_level è 2 –

+0

ho aggiunto i dettagli richiesti. fammi sapere se la domanda non è ancora chiara. Grazie. –

risposta

0

È possibile utilizzare una tabella Numbers per "creare" i passaggi incrementali. Qui è la mia messa a punto:

CREATE TABLE #floors 
    (
    [start_level] INT, 
    [end_level] INT, 
    [duration] DECIMAL(10, 4), 
    [user]  VARCHAR(50) 
) 

INSERT INTO #floors 
      ([start_level], 
      [end_level], 
      [duration], 
      [user]) 
VALUES  (1,1,10,'a'), 
      (1,2,5,'a'), 
      (2,5,27,'b'), 
      (5,6,3,'c') 

Poi, utilizzando una tabella di numeri e alcuni LEFT JOIN logica/COALESCE:

-- Create a Numbers table 
;WITH Numbers_CTE 
    AS (SELECT TOP 50 [Number] = ROW_NUMBER() 
            OVER(
             ORDER BY (SELECT NULL)) 
     FROM sys.columns) 

SELECT [start_level] = COALESCE(n.[Number], f.[start_level]), 
     [end_level] = COALESCE(n.[Number] + 1, f.[end_level]), 
     [duration] = CASE 
         WHEN f.[end_level] = f.[start_level] THEN f.[duration] 
         ELSE f.[duration]/(f.[end_level] - f.[start_level]) 
        END, 
     f.[user] 
FROM #floors f 
     LEFT JOIN Numbers_CTE n 
       ON n.[Number] BETWEEN f.[start_level] AND f.[end_level] 
       AND f.[end_level] - f.[start_level] > 1 

Ecco i passaggi logici:

  1. LEFT JOIN tabella Numeri per casi in cui end_level> = start_level + 2 (questo ha l'effetto di darci più righe - una per ogni passaggio incrementale)
  2. new start_level = If LEFT JOIN "complete s ": Prendere dalla tabella Numeri, altro: prendere la start_level originale
  3. nuovo end_level = Se il LEFT JOIN "completa": prendere Number + 1, il resto: prendere l'end_level originale
  4. nuova durata = Se end_level = start_level: prendi la durata originale (per evitare la divisione per 0), altrimenti: prendi la durata media su end_level - start_level
Problemi correlati