Selezione di dati da più tabelle in Mysql

  • Creatore Discussione Creatore Discussione ds92
  • Data di inizio Data di inizio

ds92

Nuovo Utente
28 Dic 2013
3
0
0
Salve a tutti,

In un sito che sto creando ho molte tabelle, di cui artisti e canzoni.

Devo creare una lista di canzoni, ciascuna contenente dei dati. La problematica di questa selezione è molto semplice: ogni canzone può avere più artisti. Gli artisti li vado a prelevare dalla tabella artisti. Finché è uno solo, prelevo il singolo id_artista e fine. Quando sono tanti, non so proprio come muovermi.

Il risultato che vorrei ottenere è il seguente:
artista 1 feat. artista 2 and artista 3.
(se gli ultimi due artisti non sono presenti, con le condizioni tolgo le diciture "feat." e "and".

Per una maggiore comprensione, vi espongo il codice con commenti in aggiunta.

HTML:
		<?php
		//seleziono ciclo tutte le canzoni
		$sql_list="SELECT * FROM canzoni";
		$query_list=mysql_query($sql_list);
		while ($array_list=mysql_fetch_array($query_list)) { ?>

    	<div class="single_hit">
        	<a href=""><img src="Immagini/cover/<?php echo $array_list[file] ?>" height="300" width="300" alt="<?php $array_list[titolo_canzone] ?>"  /></a>
            <div class="single_canzone_WHITE">
            	<div class="single_canzone_aside_white">#<?php echo $array_list[topcento] ?></div>
                <div class="single_canzone_bside_white">
                	<h5><?php echo $array_list[titolo_canzone] ?></h5>
                    
                    <h6>
                    <?php
			//da qui iniziano i problemi. Questo è il mio tentativo per ottenere il risultato esposto in precedenza.
                    $sql_one="SELECT * FROM canzoni, artisti WHERE canzoni.id_primo_artista = artisti.id_artista";
                    $query_one=mysql_query($sql_one);
                    $array_one=mysql_fetch_array($query_one); 
					
					 echo $array_one[nome_artista];
                        
					?> <?php if ($array_list[id_secondo_artista] != "0" ) {?>
                    
                    feat <?php
                    $sql_two="SELECT * FROM canzoni, artisti WHERE canzoni.id_secondo_artista = artisti.id_artista";
                    $query_two=mysql_query($sql_two);
                   	$array_two=mysql_fetch_array($query_two);
					
                    echo $array_two[nome_artista];
                        
					} if ($array_list[id_terzo_artista] != "0" ) {
					?> and <?php
                    $sql="SELECT * FROM canzoni, artisti WHERE canzoni.id_terzo_artista = artisti.id_artista";
                    $query=mysql_query($sql);
                    $array=mysql_fetch_array($query);
					
					echo $array[nome_artista];
                        
					} ?>
                    </h6>
                </div>
            </div>
        </div>
        <?php } ?>

Tutto questo non funziona perché durante il ciclo ogni canzone finisce per avere gli stessi artisti della prima..
vi ringrazio anticipatamente per il vs supporto
 
Riformulo la domanda perché ieri sono stato un po' impreciso nello scrivere.

Ho due tabelle, canzoni e artisti. In una pagina del sito voglio far apparire tutte le canzoni, quindi "SELECT * FROM canzoni" e fin qui ok. Considerando che ogni canzone potrebbe avere più artisti, prevedo di inserirne un massimo di 3.

Le due tabelle hanno quindi questi campi.

___CANZONI:
id_canzone (INT PRIMARY AUTO INCREMENT)
id_artista_uno (INT)
id_artista_due (INT)
id_artista_tre (INT)

___ARTISTI
id_artista (INT PRIMARY AUTO INCREMENT)
nome_artista (VARCHAR)

Supponiamo che l'artista Michael Bublé abbia, nella tabella ARTISTI, id_artista numero '5'.
Tramite pannello admin, inserisco una canzone con titoli, album, ecc e quando scelgo l'artista, dal menù a tendina (SELECT * ALL FROM artisti) scelgo Michael Bublé. In id_artista_uno mi va a riversare il '5'.

Quando faccio partire un ciclo while con "SELECT * FROM canzoni", quindi, vorrei che PHP intercettasse l'id_artista_uno di CANZONI, che in questo caso è 5, e andasse in ARTISTI a selezionare l'id_artista 5 con nome_artista Michael Bublé, in modo che io possa fare echo $array[nome_artista] e vedere il nome di Michael Bublé, non il suo numero (id_artista).

Ulteriore problematica è che questo dovrebbe farlo anche per id_artista_due e id_artista_tre durante il ciclo while.

Aiuto :(

EDIT: non ascolto Michael Bublé. :)
 
Ultima modifica:
Ti trovi nella situazione di dover relazionare i dati di due tabelle secondo uno schema di molti a molti.
Il modo in cui l'hai gestita attualmente rompe la logica relazionale del database e ti costringe a fare più query del dovuto per ricavare tutti i dati di cui hai bisogno.

Per realizzare questa associazione di dati hai bisogno di tre tabelle:

  • La prima che contenga l'elenco delle canzoni
  • La seconda che contenga l'elenco degli artisti
  • La terza che gestisca le associazioni tra canzoni e artisti.


___ARTISTI
id_artista (INT PRIMARY AUTO INCREMENT)
nome_artista (VARCHAR)
...

___CANZONI:
id_canzone (INT PRIMARY AUTO INCREMENT)
...

___ARTISTI_CANZONI
id_artista (INT)
id_canzone (INT)


In "ARTISTI_CANZONI" metti una riga per ogni artista per ogni canzone, se uno stesso artista è autore di più canzoni ti basterà mettere più righe con l'id dell'artista associato ai differenti id delle canzoni.
Più id artisti possono essere associati ad uno stesso id canzone, ottenendo così il fatto di legare nella relazione più autori (anche più di 3) ad una singola canzone.


A questo punto puoi fare un unica query, del tipo:

PHP:
$sql = "
    SELECT * 
    FROM ARTISTI_CANZONI 
        INNER JOIN CANZONI ON CANZONI.id_canzone = ARTISTI_CANZONI.id_canzone  
        INNER JOIN ARTSTI ON ARTSTI.id_artista = ARTISTI_CANZONI.id_artista";

$result = mysql_query($sql);

if (!$result)
    die('Errori Query');

/* 
    Se ci sono più artisti per una canzone, accadrà che ci sarà una riga ripetuta 
    per canzone con ogni volta i dati di un artista diverso.
    Abbiamo quindi bisogno di una variabile di "buffer" così da memorizzare la lista
    senza duplicati da visualizzare in seguito
*/
$buffer = array();

if (mysql_num_rows($result)) {
    
    #> Ciclo i record..
    while ($row = mysql_fetch_assoc($result)) {
        
        #> Se non ho ancora mai inserito questa canzone riempio il record con i dati della stessa
        if (!isset($buffer[$row['id_canzone']])) {
            $buffer[$row['id_canzone']] = array(
                'titolo' => $row['titolo_canzone']
                'etc..' => ...,
                'artisti' => array($row['id_artista'] => $row['nome_artista'])
            );

        #> Se ho già il record della canzone, significa che c'è un ulteriore artista da aggiungere
        }else {
             $buffer[$row['id_canzone']]['artisti'][$row['id_artista']] = $row['nome_artista'];
        }
    }
    mysql_free_result($result);
}

/*
A questo punto buffer sarà qualcosa tipo

Array(
    [1] => Array(
        [titolo] => Spiderman
        [altridati] => etc..
        [artisti] => Array(
            [1] => Micheal Bublè
        )
    )
)

con più di un artista sarebbe stato così:

Array(
    [1] => Array(
        [titolo] => Spiderman
        [altridati] => etc..
        [artisti] => Array(
            [1] => Micheal Bublè
            [2] => Artista X
        )
    )
)
*/

Un esempio veloce per ciclare i dati così ottenuti:
PHP:
foreach ($buffer as $canzone) {

    #> Titolo canzone
    echo $canzone['titolo'], " | ";
    
    #> Estraggo il primo artista della lista artisti per questa canzone
    $artista = array_shift($canzone['artisti']);

    #> Ci sono più artisti? Scrivo il primo, "feat" e poi unisco i nomi nell'elenco con "and"
    if (count($canzone['artisti']) > 1) {
        echo "Artisti: ", $artista, " feat ", implode(' and ', $canzone['artisti']);

    #> Altrimenti scrivo il nome dell'unico artista
    } else {
        echo "Artista: ", $artista;
    }
    
    echo "<hr />";

}


Da qui dovrebbe essere facile adattare la formattazione al tuo caso specifico ;)
 
Ti ringrazio di cuore per la risposta davvero esauriente e precisa. In particolare per quanto riguarda la creazione di una terza tabella, non ci avevo proprio pensato e questo mi faciliterà davvero le cose. Grazie infinite!
 

Discussioni simili