2012-06-05 7 views
8

Ho questa tabella con i seguenti datirighe duplicazione basati su un valore di colonna in ogni riga

Job Quantity Status Repeat 
1  100  OK  2 
2  400  HOLD 0 
3  200  HOLD 1 
4  450  OK  3 

Sulla base del valore nella colonna Ripeti per ogni riga, la riga deve essere ripetuto nuovamente. Ad esempio per il processo 1, il valore di ripetizione è 2, quindi il processo 1 dovrebbe ripetersi altre due volte.

La tabella risultante deve essere il più seguito

Job Quantity Status Repeat 
1  100  OK  2 
1  100  OK  2 
1  100  OK  2 
2  400  HOLD 0 
3  200  HOLD 1 
3  200  HOLD 1 
4  450  OK  3 
4  450  OK  3 
4  450  OK  3 
4  450  OK  3 

Qualcuno può aiutarmi con questa ricerca?

sto utilizzando sql server

+1

Esiste un limite ragionevole per i valori possibili in 'Repeat'? – Quassnoi

+0

No. Non c'è limite – user1345260

+1

Perché il downvote? – Quassnoi

risposta

10

Questo supporterà più di 7.400 ripetizioni per ogni singolo lavoro (sul mio sistema). Se è necessario altro, è possibile utilizzare una tabella di sistema diversa o un cross join.

DECLARE @d TABLE (Job INT, Quantity INT, Status VARCHAR(12), Repeat INT); 

INSERT @d SELECT 1, 100, 'OK' ,2 
UNION ALL SELECT 2, 400, 'HOLD',0 
UNION ALL SELECT 3, 200, 'HOLD',1 
UNION ALL SELECT 4, 450, 'OK' ,3; 

WITH x AS 
(
    SELECT TOP (SELECT MAX(Repeat)+1 FROM @d) rn = ROW_NUMBER() 
    OVER (ORDER BY [object_id]) 
    FROM sys.all_columns 
    ORDER BY [object_id] 
) 
SELECT * FROM x 
CROSS JOIN @d AS d 
WHERE x.rn <= d.Repeat + 1 
ORDER BY Job; 
+0

Ha funzionato. Sono un novizio, quindi puoi per favore una volta chiarire questa domanda. Non ho capito da WITH – user1345260

+1

'WITH' rappresenta una [espressione di tabella comune] (http://msdn.microsoft.com/en-us/library/ms175972.aspx). All'interno, tiriamo solo una serie di numeri da una tabella di sistema che è garantita per avere un sacco di righe (presumo che 7.400 dovrebbero essere sufficienti nel tuo caso). Usiamo 'TOP' per limitare quel numero ad uno maggiore del più grande valore di' Repeat' nella tabella. Quindi usando quei numeri eseguiamo un cross join in modo che abbiamo una riga dal CTE per ogni numero <= 'Repeat' per lavoro. E aggiungiamo anche 1 su quel lato (questo assicura che includiate anche le righe dove 'Ripeti = 0'). –

+0

Grazie. Questo è molto utile – user1345260

-1

Si può scrivere stored procedure che farà questa query (come cursore) e quindi è possibile compilare nuova tabella temporanea come si desidera

CREATE FUNCTION [dbo].[GetRepeatJobs]() 
RETURNS 
@JobsRepeatTable TABLE (JobId int, JobName nchar(10)) 
AS 
BEGIN 
DECLARE @i int 
DECLARE @j int 
DECLARE @JobId int 
DECLARE @JobName nchar(10) 

DECLARE JobsCursor CURSOR FOR (select JobId, JobName, JobRepeat from jobs) 
OPEN JobsCursor 
FETCH NEXT FROM JobsCursor INTO @JobId, @JobName, @i 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    SELECT @j = 0 
    WHILE @j < @i 
    BEGIN 
     INSERT INTO @JobsRepeatTable VALUES (@JobId, @JobName) 
     SELECT @j = @j+1  
    END 
    FETCH NEXT FROM JobsCursor INTO @JobId, @JobName, @i 
END 
RETURN 
END 

funziona perfetto per me .

+0

questo non va bene per le prestazioni ... usando WHILE (senza cursore) forse aumenti le prestazioni ... ma cte table è molto veloce – maurox

5
DECLARE @repeats TABLE 
     (
     rn INT NOT NULL PRIMARY KEY 
     ); 

WITH q (rn, m) AS 
     (
     SELECT 1, MAX(repeat) + 1 
     FROM jobs 
     UNION ALL 
     SELECT rn + 1, m 
     FROM q 
     WHERE rn < m 
     ) 
INSERT 
INTO @repeats 
SELECT rn 
FROM q 

SELECT j.* 
FROM jobs j 
CROSS APPLY 
     (
     SELECT TOP (j.repeat + 1) 
       NULL 
     FROM @repeats 
     ) q (repeat) 

Se si dispone di una tabella che ha guaranteedly più record rispetto al valore massimo possibile di repeat, si può sbarazzarsi di @repeats e l'uso che tavolo invece.

0

Preferisco l'approccio di seguito, in quanto non è affidamento su dati esterni per la query per avere successo ed è abbastanza semplice. Ho usato il codice di Aaron Bertrand per inizializzare la tabella dei dati, ma il mio approccio su come ripetere i dati - questo approccio non richiede una tabella specifica per contenere più file rispetto alle ricorsioni richieste/non dipendenti da dati esterni.

DECLARE @d TABLE (Job INT, Quantity INT, Status VARCHAR(12), Repeat INT); 

INSERT @d SELECT 1, 100, 'OK' , 2 
UNION ALL SELECT 2, 400, 'HOLD', 0 
UNION ALL SELECT 3, 200, 'HOLD', 1 
UNION ALL SELECT 4, 450, 'OK' , 3; 

DECLARE @maxRecursion INT; 
SET @maxRecursion = (SELECT MAX(Repeat) 
         FROM @d);  

WITH Iterator AS 
(
    SELECT 1 AS Iterations 
    UNION ALL 
    SELECT Iterations + 1 FROM Iterator WHERE Iterations < @maxRecursion 
) 

SELECT A.* 
    FROM @d AS A 
RIGHT JOIN Iterator ON Iterator.Iterations <= (A.Repeat + 1) 
ORDER BY Job ASC 
OPTION (MAXRECURSION 0) 

Cheers!

Problemi correlati