RIPETIZIONE RIGHE IN RELAZIONE A RECORD

di il
12 risposte

RIPETIZIONE RIGHE IN RELAZIONE A RECORD

Salve ragazzi,
ho questa tabella qui:
select id_Ar, descr_Ar, Qta_Ar
from AR
order by id_Ar
ottenendo, ad esempio
-------------------------------
1 | ALIMENTATORE | 2
2 | CASE | 1
3 | DESKTOP | 3
--------------------------------
però vorrei ottenere che tutta la riga completa di duplicasse in relazione alla quantità:
--------------------------------
1 | ALIMENTATORE | 2
1 | ALIMENTATORE | 2
2 | CASE | 1
3 | DESKTOP | 3
3 | DESKTOP | 3
3 | DESKTOP | 3
----------------------------------
come posso modificare il codice? Il codice usato sopra è per far capire la richiesta

12 Risposte

  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Ciao,

    fossi in te spiegherei meglio l'esigenza del perché ti serve questa strana cosa
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Salve,
    NON discuto la richiesta, che anche per me come per @sspintux e' quantomeno "discutibile", ma comunque la cosa e' fattibile..
    utilizziamo una generazione lineare basata su sys.all_columns (che sulla versione 2019 di SQL Server produce 11k righe)...
    se hai gia' a disposizione, come spesso succede, una tabella di "Numeri" puri sequenziale, puoi usare quella al suo posto...

    quindi, unendo i "pezzi", generiamo MAX(Qt) righe, che poi mettiamo in crosso join con la tabella desiderata, ed il filtro di where effettua la pulizia desiderata...
    
    DECLARE @t TABLE (
    	Id int NOT NULL,
    	Data varchar(5) NOT NULL,
    	Qt int NOT NULL
    	);
    
    INSERT INTO @t
    	VALUES (1, 'a', 1), (2, 'b', 2), (3, 'c', 3);
    
    WITH cte AS (
      SELECT TOP (SELECT MAX(Qt) FROM @t) rn = ROW_NUMBER()  OVER (ORDER BY [object_id]) 
    	FROM sys.all_columns 
    	ORDER BY [object_id]
    	)
    	SELECT t.* 
    		FROM @t t
    			CROSS JOIN cte
    		WHERE cte.rn <= t.Qt
    	ORDER BY t.Id;
    
    
    select * from sys.all_columns 
    --<-----------
    Id          Data  Qt
    ----------- ----- -----------
    1           a     1
    2           b     2
    2           b     2
    3           c     3
    3           c     3
    3           c     3	
    
    salutoni romagnoli
    --
    Andrea
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Grazie mille domani lo proverò. In reatà è una richiesta che mi è stata fatta da un cliente. Mi occuopo di personalizzazione di report per un software gestionale. In pratica voleva realizzare un report in cui non veniva visualizzato il solito modulo con "codice/descrizione/quantita/prezzo...ecc" ma che gli venissero scritti gli articoli uno sotto l'altro senza la quantità in modo che nel momento di carico della merce potessero spuntarli a mano a mano. Non so se sono stato chiaro
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    asql ha scritto:


    Salve,
    NON discuto la richiesta, che anche per me come per @sspintux e' quantomeno "discutibile", ma comunque la cosa e' fattibile..
    utilizziamo una generazione lineare basata su sys.all_columns (che sulla versione 2019 di SQL Server produce 11k righe)...
    se hai gia' a disposizione, come spesso succede, una tabella di "Numeri" puri sequenziale, puoi usare quella al suo posto...

    quindi, unendo i "pezzi", generiamo MAX(Qt) righe, che poi mettiamo in crosso join con la tabella desiderata, ed il filtro di where effettua la pulizia desiderata...
    
    DECLARE @t TABLE (
    	Id int NOT NULL,
    	Data varchar(5) NOT NULL,
    	Qt int NOT NULL
    	);
    
    INSERT INTO @t
    	VALUES (1, 'a', 1), (2, 'b', 2), (3, 'c', 3);
    
    WITH cte AS (
      SELECT TOP (SELECT MAX(Qt) FROM @t) rn = ROW_NUMBER()  OVER (ORDER BY [object_id]) 
    	FROM sys.all_columns 
    	ORDER BY [object_id]
    	)
    	SELECT t.* 
    		FROM @t t
    			CROSS JOIN cte
    		WHERE cte.rn <= t.Qt
    	ORDER BY t.Id;
    
    
    select * from sys.all_columns 
    --<-----------
    Id          Data  Qt
    ----------- ----- -----------
    1           a     1
    2           b     2
    2           b     2
    3           c     3
    3           c     3
    3           c     3	
    
    salutoni romagnoli
    --
    Andrea
    Ciao Andrea, ho provato il tuo codice però mi compare il messaggio "Il numero di righe fornite per il parametro del conteggio righe della clausola TOP o FETCH deve essere un intero". Credo sia dovuto al fatto che il mio "Qt" sia di tipo "numeric" invece di "int" purtroppo lavoro su DB già creati non sono create da me le tabelle. Posso convertirlo in qualche modo in un tipo intero?
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    asql ha scritto:


    ...utilizziamo una generazione lineare basata su sys.all_columns (che sulla versione 2019 di SQL Server produce 11k righe)...
    se hai gia' a disposizione, come spesso succede, una tabella di "Numeri" puri sequenziale, puoi usare quella al suo posto...
    E se eventualmente si utilizzasse un ricorsiva per generare la progressione?
    DECLARE @max as int
    DECLARE @t TABLE (
    	Id int NOT NULL,
    	Data varchar(5) NOT NULL,
    	Qt int NOT NULL
    	);
    
    INSERT INTO @t
    	VALUES (1, 'a', 1), (2, 'b', 2), (3, 'c', 3);
    
    SET @max = (SELECT MAX(qt) FROM @t);
    
    WITH cte AS(
    SELECT 1 as num
    UNION ALL
    SELECT num + 1 as num FROM cte Where num < @max
    )
    
    Select *
    from cte
    Cross JOIN @t T
    Where T.Qt >= cte.num
    Order By T.Id
    OPTION (MAXRECURSION 1000);
    
    Onestamente i piani di esecuzione sono una bestia che sto ancora studiando e quindi chiedo...
    Utilizzando il codice di @asql, ho come costi relativi ai batch:
    - per Query 1 (INSERT INTO ...) ->16%;
    - per Query 2 (WITH cte AS ...) -> 84%;

    Con il mio ho:
    - per Query 1 (INSERT INTO ...) -> 36%;
    - per Query 2 (SET @max ...) -> 12%;
    - per Query 3 (WITH cte AS ...) -> 53%.

    Partendo dal presupposto che il batch per l'INSERT è identico in entrambi i casi, e vedendo l'incidenza calcolata sul costo totale, posso dedurne che una cte ricorsiva in questo caso è più efficiente?
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    nicoSQLforum ha scritto:


    Posso convertirlo in qualche modo in un tipo intero?
    prova a convertire con CAST (1.2 as int)
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Provate anche questa se volete
    
    use tempdb
    go
    
    DECLARE @t TABLE (
    	Id int NOT NULL,
    	Data varchar(5) NOT NULL,
    	Qt numeric(10,0) NOT NULL
    	);
    
    INSERT INTO @t
    	VALUES (1, 'a', 4), (2, 'b', 5), (3, 'c', 3);
    
    	;with cte as 
    	(
    		select id, data, Qt ,n=1 from @t
    		union all
    		select id, data, qt, n=n+1 from cte  c
    		where c.n<(select cast(t.qt as int) from @t t where t.id=c.id)
    	)
    	select  * from cte order by id,n
    	OPTION (MAXRECURSION 1000); -- N.B. occhio se sono più di 1000 righe da stampare
    
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Sgrubak ha scritto:



    E se eventualmente si utilizzasse un ricorsiva per generare la progressione?
    
    WITH cte AS(
    SELECT 1 as num
    UNION ALL
    SELECT num + 1 as num FROM cte Where num < @max
    )
    ...
    
    buono !


    salutoni romagnoli
    --
    Andrea
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Ciao a tutti,
    riguardo l'appunto di @Sgrubak sull'efficienza, la tua valutazione e' solo sull'incidenza del costo della singola operazione del batch NEL CONTESTO DELL'INTERO BATCH, quindi non e' veramente una valutazione di efficienza mediata tra la CTE e la proiezione su syscolumns...

    detto cio', visto che presumibilmente NON si avra' mai bisogno di una popolazione di 11k righe (o almeno vorrei sperarlo) da mettere in crossjoin, probabilmente la CTE ricorsiva puo' essere piu' performante.

    La soluzione migliore, mi ripeto, sarebbe la classica tabella Numeri gia' popolata che tanti di noi gia' hanno nei propri database proprio per rispondere a queste esigenze al fine di non dover materializzare sequenze...

    salutoni romagnoli
    --
    Andrea
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Ok, grazie Andrea!
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    sspintux ha scritto:


    nicoSQLforum ha scritto:


    Posso convertirlo in qualche modo in un tipo intero?
    prova a convertire con CAST (1.2 as int)
    Ok, va tutto perfetto l'unico problema è che c'è una riga la cui quantità è di 0.5 e facendo cosi vado a perderla. Come potrei proseguire?
    Perchè ci sono degli articoli che hanno l'unita di misura in 'Pezzi' quindi per forza interi ed io credevo di aver risolto con il CAST. Poi pero mi sono reso conto che esistono anche alcuni articoli che sono in 'Metri' che fin quando sono >1 non c'è nessun problema. Ma quando è 0.5 non me lo fa comparire in tabella
  • Re: RIPETIZIONE RIGHE IN RELAZIONE A RECORD

    Vedi le funzioni CEILING e FLOOR
Devi accedere o registrarti per scrivere nel forum
12 risposte