none
Copia di dati con condizione RRS feed

  • Domanda

  • Buongiorno a tutti,

    sto imparando a mettere le mani sui database sql (in particolare sto lavorando su sql server 2008) da pochi giorni e da autodidatta.

    Ho fatto piccolissime cose e ora vorrei chiedere un consiglio su come procedere per fare una copia. Ora vi spiego la mia situazione.

    Tabella: PrezzoArticolo

    Articolo;Magazzino;Prezzo

    1;2;2

    1;10;1

    2;2;5

    2;10;4

    3;2;1

    3;10;1

    Come potete vedere ho degli stessi articoli stoccati in diversi magazzini. In base al magazzino ho un prezzo diverso.

    Ora però devo far si che il prezzo degli articoli sia uguale per tutti i magazzini.

    Il prezzo di riferimento per gli articoli sarà quello del magazzino 2 e che quindi dovrà essere copiato anche nel magazzino 10.

    Ho pensato a una query con l'uso di update, set e where, però poi mi sono reso conto che non sapevo come indicare che l'origine dei dati da copiare doveva essere il magazzino 2.

    Ecco una bozza di quello che ho fatto finora:

    Update PrezzoArticolo set PrezzoArticolo.Prezzo = (valore contenuto in PrezzoArticolo.Prezzo del magazzino 2) 
    where PrezzoArticolo.Magazzino = 10

    La parte in grassetto è quella che mi tiene fermo.

    Qualcuno sa aiutarmi?

    Grazie mille...

    crash1983









    • Modificato Crash1983 martedì 17 settembre 2013 13:50
    martedì 17 settembre 2013 13:41

Tutte le risposte

  • Ciao Crash,

    quello che ti serve è una query di UPDATE con join tra tabelle (che, nel nostro caso, sono la stessa tabella). Una cosa di questo tipo:

    UPDATE P1 SET Prezzo = P2.Prezzo
    FROM PrezzoArticolo P1 INNER JOIN PrezzoArticolo P2 ON P2.Articolo  = P1.Articolo AND
                                                           P2.Magazzino = 2
    WHERE P1.Magazzino = 10

    Dove esegui il join sulla PrezzoArticolo in base al codice articolo + magazzino, dando un alias alle due tabelle e specificando quindi che la prima deve prendere il prezzo della seconda.

    Prima di eseguire, mi raccomando il backup dei dati!


    Emiliano Musso

    martedì 17 settembre 2013 14:15
  • Ciao Crash,

    ti posto una soluzione alternativa.

    UPDATE dbo.PrezzoArticolo 
    SET Prezzo = (Select Prezzo FROM dbo.PrezzoArticolo as PATemp 
    WHERE PATemp.Articolo=dbo.PrezzoArticolo.Articolo AND PATemp.Magazzino=2) WHERE dbo.PrezzoArticolo.Magazzino=10

    [cit.] Prima di eseguire, mi raccomando il backup dei dati! ;-)


    martedì 17 settembre 2013 14:24
  • Grazie ad entrambi per l'aiuto.

    Ho provato le due soluzioni e funzionano ma hanno dei comportamenti differenti su alcune cose:

    La prima mi copia solo i prezzi degli articoli che sono presenti su entrambi i magazzini.

    La seconda mi copia tutti i prezzi, ma allo stesso tempo rende 'Null' quelli del magazzino 10 nel caso in cui l'articolo è presente nel magazzino 10 ma non nel 2.

    Mi rendo conto che le cose si complicano un pochino, perchè oltre ad aggiornare i prezzi dovrei anche avere una copia esatta dei due magazzini (quello di riferimeno è il 2), cioè gli articoli non presenti nel magazzino 10 ma presenti nel 2 devono essere aggiunti al 10 e di contro quelli presenti nel 10 ma non presenti nel 2 devono essere eliminati dal 10.

    Grazie ancora per il supporto

    crash1983

    martedì 17 settembre 2013 15:09
  • Puoi allora provare questa versione:

    UPDATE P1 SET Prezzo = ISNULL(P2.Prezzo, 0)
    FROM PrezzoArticolo P1 LEFT JOIN PrezzoArticolo P2 ON P2.Articolo  = P1.Articolo AND
                                                           P2.Magazzino = 2
    WHERE P1.Magazzino = 10

    In questo modo, il JOIN tra le tabelle non è obbligatorio, e nel caso non venga trovato il magazzino 2, il valore scritto sarà 0 e non NULL.


    Emiliano Musso

    martedì 17 settembre 2013 15:48
  • salve,

    anche qui farei uso dell'istruzione MERGE... e' un'istruzione potentissima con la quale puoi effettuare un confronto semplice sia di intersezione che esclusione, ed effettuare l'operazione desiderata in tutti e 3 i casi di confronto:

    1: l'articolo esiste in entrambi i magazzini= va aggiornato magazzino 10

    2: l'articolo esiste solo in mag2, quindi va inserito in mag10

    3: l'articolo esiste solo in mag10, quindi va eliminato da mag10

    trivialmente,

    SET NOCOUNT ON;
    USE tempdb;
    GO
    CREATE TABLE dbo.PrezzoArticolo (
    	Articolo int,
    	Magazzino int,
    	Prezzo int
    	);
    GO
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 1, 2, 2);
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 1, 10, 1);
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 2, 2, 5);
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 2, 10, 4);
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 3, 2, 1);
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 3, 10, 1);
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 4, 2, 1);
    INSERT INTO dbo.PrezzoArticolo
    	VALUES ( 5, 10, 1);
    
    GO
    PRINT 'indicazione delle intersezioni o esclusioni di appartenenza';
    WITH m2 AS (
    	SELECT *
    		FROM dbo.PrezzoArticolo
    		WHERE Magazzino = 2),
    m10 AS (
    	SELECT *
    		FROM dbo.PrezzoArticolo
    		WHERE Magazzino = 10)
    SELECT *
    	FROM m2 FULL OUTER JOIN m10 ON m10.Articolo = m2.Articolo;
    GO
    WITH m2 AS (
    	SELECT *
    		FROM dbo.PrezzoArticolo
    		WHERE Magazzino = 2),
    m10 AS (
    	SELECT *
    		FROM dbo.PrezzoArticolo
    		WHERE Magazzino = 10)
    	MERGE m10 AS target
    		USING m2 AS source ON target.Articolo = source.Articolo
    		WHEN MATCHED THEN 
    			UPDATE SET target.Prezzo = source.Prezzo
    		WHEN NOT MATCHED BY TARGET THEN
    			INSERT (Articolo, Magazzino, Prezzo) VALUES (source.Articolo, 10, source.Prezzo)
    		WHEN NOT MATCHED BY SOURCE THEN
    			DELETE;
    GO
    PRINT 'indicazione delle intersezioni o esclusioni di appartenenza';
    WITH m2 AS (
    	SELECT *
    		FROM dbo.PrezzoArticolo
    		WHERE Magazzino = 2),
    m10 AS (
    	SELECT *
    		FROM dbo.PrezzoArticolo
    		WHERE Magazzino = 10)
    SELECT *
    	FROM m2 FULL OUTER JOIN m10 ON m10.Articolo = m2.Articolo;
    GO
    DROP TABLE dbo.PrezzoArticolo;
    --<---------------
    indicazione delle intersezioni o esclusioni di appartenenza
    Articolo    Magazzino   Prezzo      Articolo    Magazzino   Prezzo
    ----------- ----------- ----------- ----------- ----------- -----------
    1           2           2           1           10          1
    2           2           5           2           10          4
    3           2           1           3           10          1
    NULL        NULL        NULL        5           10          1
    4           2           1           NULL        NULL        NULL
    
    indicazione delle intersezioni o esclusioni di appartenenza
    Articolo    Magazzino   Prezzo      Articolo    Magazzino   Prezzo
    ----------- ----------- ----------- ----------- ----------- -----------
    1           2           2           1           10          2
    2           2           5           2           10          5
    3           2           1           3           10          1
    4           2           1           4           10          1
    

    comprendo che possa esserci parecchio da "digerire" specialmente se sei un neofita, ma se ho ben compreso le tue esigenze, mi sembra una soluzione ottimale, basata competamente su set di risultati e molto lineare...

    saluti


    http://www.hotelsole.com/asql/index.php - DbaMgr2k - DbaMgr and further SQL Tools http://www.hotelsole.com/

    giovedì 19 settembre 2013 20:38
    Moderatore