none
Split valori RRS feed

  • Domanda

  • Ciao a tutti, devo creare istruzioni di select, update e insert su una tabella in cui un campo è una lista di ID, come faccio a splittarli?

    Quindi se il mio campo Lista_Giocatori della tabella Utenti è formato da questi valori 1, 2, 3, 4, 5, 6 devo fare una select che tiri fuori tutte le righe con questi ID in un altra tabella.

    es.
    Tabella Utenti
    _______________________
    Nome testo
    Cognome testo
    Lista_Giocatori 1,2,3,4,5,6


    es.
    Tabella Giocatori
    ____________________
    Nome Cristiano
    Cognome Ronaldo
    Id_Giocatore 6

    Come tiro fuori tutti i giocatori di quell'utente?

    Grazie
    giovedì 7 aprile 2011 13:48

Tutte le risposte

  • Ciao a tutti, devo creare istruzioni di select, update e insert su una tabella in cui un campo è una lista di ID, come faccio a splittarli?

    Quindi se il mio campo Lista_Giocatori della tabella Utenti è formato da questi valori 1, 2, 3, 4, 5, 6 devo fare una select che tiri fuori tutte le righe con questi ID in un altra tabella.

    es.
    Tabella Utenti
    _______________________
    Nome testo
    Cognome testo
    Lista_Giocatori 1,2,3,4,5,6


    es.
    Tabella Giocatori
    ____________________
    Nome Cristiano
    Cognome Ronaldo
    Id_Giocatore 6

    Come tiro fuori tutti i giocatori di quell'utente?


    Ciao Dario,

    La difficoltà che riscontri è riconducibile al fatto che la tabella Utenti non rispetta la prima forma normale, pertanto stai cercando di far fare al DBMS una interrogazione che vìola i principi dell'algebra relazionale.

    Il consiglio che ti posso dare è quello di rivedere e normalizzare alla terza forma normale la struttura del DBMS. Se questa operazione non è perseguibile (ahimé), non ti resta che giocare con le funzioni stringa per cercare di ottenere in qualche modo il risultato che ti aspetti (ti assicuro che NON ne vale la candela).

    Inoltre non ho capito bene nel dettaglio quale sia questo risultato, quindi ti invito a postare i comandi di CREATE TABLE delle due tabelle, alcune righe di prova (INSERT INTO) ed il result set che vorresti ottenere con quei dati.

    Ciao!


    Lorenzo Benaglia
    Microsoft MVP - SQL Server
    http://blogs.dotnethell.it/lorenzo
    http://social.technet.microsoft.com/Forums/it-IT/sqlserverit
    giovedì 7 aprile 2011 19:12
    Moderatore
  • salve,

    al di la' che ovviamente concordo con tutto quanto detto da Lorenzo, puoi giocare sicuramente con le stringhe come lui stesso gia' ha detto... ovviamente non si tratta di operazioni performanti ma giusto per il gusto di farlo potresti anche scrivere

    SET NOCOUNT ON;
    GO
    USE tempdb;
    GO
    CREATE TABLE dbo.Players (
    	Id int NOT NULL PRIMARY KEY,
    	Nome varchar(10) NOT NULL
    	);
    CREATE TABLE dbo.Teams (
    	Id int NOT NULL PRIMARY KEY,
    	Nome varchar(10) NOT NULL,
    	Players varchar(100)
    	);
    GO
    INSERT INTO dbo.Players
    	VALUES ( 1, 'Lorenzo' ),
    			( 2, 'Andrea' ),
    			( 3, 'Luca' ),
    			( 4, 'Chico' ),
    			( 5, 'Giorgio' ),
    			( 6, 'Marcello' ),
    			( 7, 'Daniele' );
    
    INSERT INTO dbo.Teams 
    	VALUES ( 1, 'Nord', '1,4,5,6' ),
    	      ( 2, 'Sud', '2,3,7' );
    GO
    DECLARE @sep char(1) = ',';
    
    WITH Pieces AS (
    	SELECT t.Id AS [Team], 1 pn, 1 [start], CHARINDEX(@sep, t.Players) [stop], t.Players AS [FullPlayers]
    		FROM dbo.Teams t
    	UNION ALL
    	SELECT p.Team AS [Team], pn + 1, [stop] + 1, CHARINDEX(@sep, FullPlayers, [stop] + 1), FullPlayers AS [FullPlayers]
    		FROM Pieces p			
    		WHERE [stop] > 0
    	),
    ctePlayers AS (
    	SELECT p.Team, SUBSTRING(FullPlayers, start, CASE WHEN stop > 0 THEN stop-start ELSE 8000 END) AS Player
    		FROM Pieces p
    	)
    	SELECT t.Id, t.Nome, g.Nome
    	FROM dbo.Teams t
    		JOIN ctePlayers c ON c.Team = t.Id
    		JOIN dbo.Players g ON g.Id = c.Player
    
    	ORDER BY t.Id, g.Nome;
    GO
    DROP TABLE dbo.Players, dbo.Teams;
    --<----------------------
    Id     Nome    Nome
    ----------- ---------- ----------
    1      Nord    Chico
    1      Nord    Giorgio
    1      Nord    Lorenzo
    1      Nord    Marcello
    2      Sud    Andrea
    2      Sud    Daniele
    2      Sud    Luca
    
    

    questa cte ricorsiva funziona solo se "l'elenco" di idGiocatori rientra nella massima ricorsione di default (100), diversamente andrebbe impostata specificatamente sul livello di ricorsione desiderato, ma questo non contribuisce sicuramente a "migliorare" qualche cosa che gia' e' profondamente "ributtante" :) ... comunque puoi sempre eventualmente risolvere scrivendo una funzione utente che esegua lo "split" della colonna Lista_Giocatori e che ritorni una tabella con gli Id dei giocatori stessi, allo stesso modo di quanto fa la common table expression ricorsiva qui utilizzata...

    ripeto, tutto cio' costituisce solo un "divertimento" relativamente all'uso della sintassi, e non andrebbe utilizzato in produzione come Lorenzo ha ampiamente documentato..

    saluti


    http://www.asql.biz - DbaMgr2k - DbaMgr and further SQL Tools http://www.hotelsole.com/ - http://www.hotelsolericcione.de
    venerdì 8 aprile 2011 00:47
    Moderatore
  • On 4/7/2011 3:48 PM, darioweb wrote:

    Ciao a tutti, devo creare istruzioni di select, update e insert su una tabella in cui un campo è una lista di ID, come faccio a splittarli?

    Quindi se il mio campo Lista_Giocatori della tabella Utenti è formato da questi valori 1, 2, 3, 4, 5, 6 devo fare una select che tiri fuori tutte le righe con questi ID in un altra tabella.

    es.
    Tabella Utenti
    _____________________
    Nome testo
    Cognome testo
    Lista_Giocatori 1,2,3,4,5,6


    es.
    Tabella Giocatori
    __________________
    Nome Cristiano
    Cognome Ronaldo
    Id_Giocatore 6

    Come tiro fuori tutti i giocatori di quell'utente?

    Dando per scontato che tu abbia letto i suggerimenti degli MVPs, se il db è legacy :) potresti prima tirarti su il record Utente, eseguire uno split per separatore e rifare una query IN con tutti gli Id ricavati al punto precedente.


    Tommaso Caldarola http://www.caldarola.net http://dotnetside.org/blogs/tcaldarola/
    venerdì 8 aprile 2011 07:36