structure d'une base de données

mou
Invité n'ayant pas de compte PHPfrance

08 févr. 2006, 13:25

Bonjour.

Je souhaiterais avoir votre avis, et de l'aide si possible, sur un problème que j'ai dans l'élaboration d'une base de données. Voilà ce que je souhaite faire.

On rentre le nom d'une chanson dans un moteur de recherche.

Suite à cela nous arrive une liste avec :

- l'artiste qui a interprété une chanson (ils peuvent être plusiuers à avoir interprété la chanson et il peut y avoir des duos aussi).

- l'émission dans laquelle il l'a interprétée


Le problème c'est que je souhaiterais que pour chaque artiste, chaque duo il y ait un lien vers l'émission et vers une fiche de l'artiste en question.

J'avais pensé à une table avec des champs artiste solo1, artiste solo2..., artiste duo1a, artisteduo1b, artisteduo2a, artisteduo2b...,

Enfin bref, ce serait du bidouillage.

Est ce que je suis assez clair ?

Avez vous une solution à me proposer ?

Merci pour votre aide...

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

08 févr. 2006, 14:03

Tu l'as dit:
... une chanson ...
... l'artiste qui a interprété une chanson (ils peuvent être plusiuers à avoir interprété la chanson et il peut y avoir des duos aussi)...
... l'émission dans laquelle il l'a interprétée.
Pour construire la base de données relationnelle je dois reformuler le besoin :
  • 1 chanson est interprétée par 1 artiste plusieurs fois ou 2 artistes plusieurs fois = des artistes plusieurs fois dans plusieurs émissions.
    1 chanson est interprétée dans le cadre de plusieurs émissions.

    La meilleure façon de savoir si l'interprétation est faite par un duo est de
    se référer au temps et à l'émission dans la quelle l'interprétation à eu lieu.
Ce qui donne le modèle suivant :

Table Chanson 1--- liée à --->N Table Interprétation
et
Table Artiste 1--- liée à --->N Table Interprétation
et
Table Emission 1--- liée à --->N Table Interprétation

Les occurences des interprétations peuvent être repérées (clé primaire)par une date, une chanson, une émission et un artiste.

Donc :
La table Interprétation contient les champs :
  • 1. date : la date d'interprétation
    2. chanson : lien vers l'id de la chanson dans la table Chanson
    3. artiste : lien vers l'id de l'artiste dans la table Artiste
    4. émission : lien avec l'id de l'émission dans la table Emission
Car c'est une table centrale et c'est elle qui va contenir le détail des interprétations (tuple : date, chanson, artiste, émission)

Quand au moins 2 tuples (date, chanson, artiste, émission) ont la même date, chanson et émission : alors les artistes concernés forment un duo.

Par extension : Quand au moins N tuples ont la même date, chanson et émission : alors les artistes concernés forment un groupe d'interpréteurs.
Modifié en dernier par sadeq le 09 févr. 2006, 09:42, modifié 1 fois.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

mou
Invité n'ayant pas de compte PHPfrance

08 févr. 2006, 15:18

Merci pour ton aide. Petite question tout de même, je ne connais pas la notion de "tuple".

Perso j'avais pensé après à deux tables.

Table artiste : nom, chanson, emission, bio
Table duo : nom1, nom2, emission, bio1, bio2

Ensuite il me suffisait de faire un select pour chacun de ces tables ce qui m'afficherait dans une premie temps, les chanteurs (single) et ensuite les duos. Ca devrait marcher mais bon, comme j'aime bien apprendre je ne suis pas contre une petite démonstration (explication détaillée) sur le schéma que tu proposais (si tu as le temps bien entendu). En tout cas, merci pour l'info.

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

09 févr. 2006, 11:51

Tiens voici un exemple :

Artistes & chansons

La base de données SQL:
-- phpMyAdmin SQL Dump
-- version 2.7.0-pl1
-- http://www.phpmyadmin.net
-- 
-- Serveur: localhost
-- Généré le : Mercredi 15 Février 2006 à 09:46
-- Version du serveur: 5.0.17
-- Version de PHP: 5.1.1
-- 
-- Base de données: `artistes_chansons`
-- 
CREATE DATABASE `artistes_chansons` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE artistes_chansons;

-- --------------------------------------------------------

-- 
-- Structure de la table `artiste`
-- 

CREATE TABLE `artiste` (
  `id` int(11) NOT NULL auto_increment,
  `nom` varchar(50) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `nom` (`nom`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;

-- 
-- Contenu de la table `artiste`
-- 

INSERT INTO `artiste` (`id`, `nom`) VALUES (4, 'Bix BEIDERBECKE');
INSERT INTO `artiste` (`id`, `nom`) VALUES (5, 'Don VOORHEES');
INSERT INTO `artiste` (`id`, `nom`) VALUES (7, 'JOHNTONE');
INSERT INTO `artiste` (`id`, `nom`) VALUES (6, 'LAYTON');
INSERT INTO `artiste` (`id`, `nom`) VALUES (3, 'Paul WHITEMAN');

-- --------------------------------------------------------

-- 
-- Structure de la table `chanson`
-- 

CREATE TABLE `chanson` (
  `id` int(11) NOT NULL auto_increment,
  `nom` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `nom` (`nom`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

-- 
-- Contenu de la table `chanson`
-- 

INSERT INTO `chanson` (`id`, `nom`) VALUES (2, 'Clementine From New Orleans');
INSERT INTO `chanson` (`id`, `nom`) VALUES (1, 'Ol Man River');

-- --------------------------------------------------------

-- 
-- Structure de la table `emission`
-- 

CREATE TABLE `emission` (
  `id` int(11) NOT NULL auto_increment,
  `nom` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `nom` (`nom`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

-- 
-- Contenu de la table `emission`
-- 

INSERT INTO `emission` (`id`, `nom`) VALUES (1, 'Black & Blue');
INSERT INTO `emission` (`id`, `nom`) VALUES (2, 'Chanson - Boum !');
INSERT INTO `emission` (`id`, `nom`) VALUES (5, 'LES CINGLES DU MUSIC-HALL (1782)');

-- --------------------------------------------------------

-- 
-- Structure de la table `interpretation`
-- 

CREATE TABLE `interpretation` (
  `lieu` varchar(100) NOT NULL,
  `date` datetime NOT NULL,
  `id_emission` int(11) NOT NULL,
  `id_chanson` int(11) NOT NULL,
  `id_artiste` int(11) NOT NULL,
  PRIMARY KEY  (`date`,`id_emission`,`id_chanson`,`id_artiste`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 
-- Contenu de la table `interpretation`
-- 

INSERT INTO `interpretation` (`lieu`, `date`, `id_emission`, `id_chanson`, `id_artiste`) VALUES ('New York', '1927-09-10 00:00:00', 5, 2, 5);
INSERT INTO `interpretation` (`lieu`, `date`, `id_emission`, `id_chanson`, `id_artiste`) VALUES ('New York', '1928-01-07 00:00:00', 5, 1, 3);
INSERT INTO `interpretation` (`lieu`, `date`, `id_emission`, `id_chanson`, `id_artiste`) VALUES ('New York', '1928-01-07 00:00:00', 5, 1, 5);
INSERT INTO `interpretation` (`lieu`, `date`, `id_emission`, `id_chanson`, `id_artiste`) VALUES ('Londres', '1928-05-10 00:00:00', 5, 1, 6);
INSERT INTO `interpretation` (`lieu`, `date`, `id_emission`, `id_chanson`, `id_artiste`) VALUES ('Londres', '1928-05-10 00:00:00', 5, 1, 7);
INSERT INTO `interpretation` (`lieu`, `date`, `id_emission`, `id_chanson`, `id_artiste`) VALUES ('Chicago', '1928-07-07 00:00:00', 5, 1, 4);
Liste des interprétations par émission:
SELECT e.nom, date, lieu, c.nom, a.nom 
FROM interpretation as i , emission as e, chanson as c, artiste as a
WHERE i.id_artiste = a.id 
AND i.id_chanson = c.id 
AND i.id_emission = e.id
ORDER BY e.nom, date, lieu, c.nom, a.nom
Comme on le voit ici le WHERE s'occupe principalement des relations entre les tables.

Pour savoir le type "Single" ou "Duo" de l'interprétation :
SELECT  id_emission, date, lieu, id_chanson, if (count(id_artiste) <2 , "Single" , "Duo") as type
FROM interpretation 
GROUP BY id_emission, date, lieu, id_chanson
Cette requête ne permet pas d'avoir accès aux artistes, puisqu'il y a un regroupement par chanson. Le cas des Duo le démontre.

Pour sélectionner les "Duo" par leur nom :
SELECT e.nom, i.date, i.lieu, c.nom, types.type, (SELECT nom FROM artiste WHERE i.id_artiste = id) AS nom_artiste
FROM (
      SELECT id_emission, date, lieu, id_chanson, if( count( id_artiste ) <2, "Single", "Duo" ) AS TYPE 
      FROM interpretation
      GROUP BY id_emission, date, lieu, id_chanson
) AS TYPES , 
interpretation AS i, emission as e, chanson as c

WHERE types.type = "Duo"
AND i.id_emission = types.id_emission
AND i.date = types.date
AND i.id_chanson = types.id_chanson
AND i.id_emission = e.id
AND i.id_chanson = c.id
La sous-requête "(SELECT nom FROM artiste WHERE i.id_artiste = id) AS nom_artiste" qui se trouve dans le SELECT
principal permet de définir le champ nom de l'artiste vu que cette info n'est pas accèssible par le FROM principal.

La sous-requête nommée TYPES dans le FROM principal rappelle la requête qui determine le type "Single" et "Duo".

Les autres tables permettent l'accès aux infos interpretation, emission et chanson.

Le WHERE s'occuppe à la fois de ne sélectionner que les "Duo" et de mettre en relation les tables et la sous-requête TYPES.
Modifié en dernier par sadeq le 15 févr. 2006, 10:44, modifié 1 fois.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

mou
Invité n'ayant pas de compte PHPfrance

10 févr. 2006, 17:08

Merci bcp bcp.

Je susi en train d'adapter tou cela à mes données et pour le moment ça a l'air de foctionner. Merci d'avoir pris le temps de m'aider.

A+

Invité
Invité n'ayant pas de compte PHPfrance

13 févr. 2006, 17:09

Le code que tu m'as donné est nikel. Le seul problèmes est que lorsque j'affiche les résultats des duos, j'ai deux fois la même ligne avec les mêmes infos car justement il s'agit d'un duo. Ce que je souhaiterais c'est un truc du genre :
Duo
Nom 1 et Nom 2 - emission du 20/12/2005

Et non pas :
Nom1 - emission du 20/12/2005
Nom2 - emission du 20/12/2005

Mon code est le suivant :
// on envoie la requête
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());

// on fait une boucle qui va faire un tour pour chaque enregistrement

echo 'Le titre <b>gh</b> a été interprété en Duo par : <br><br>';

while($data = mysql_fetch_assoc($req))
{
// on affiche les informations de l'enregistrement en cours

echo '<b>'.$data['nom_artiste'].'</b> - Emission diffusée le ('.$data['date'].')<br> ';

}

echo'<br><br>';


Merci pour ton aide si tu en as le temps. Bien entendu, toute personne pouvant m'aider est la bienvenue ! ;-) Je me rends bien compte que vous me machez le travail mais j'apprends à travers votre expérience et c'est très sympa.

Merci

PS : autre question que je me posais
si j'écris '.$data['nom_artiste'].' cela m'affiche la valeur contenue dans le champ nom_artiste. Mais si j'ai plusieurs tables qui ont le même nom de champ, puis-je le spécifier quelque part, su style '.$data['table1.nom_artiste'].'

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

14 févr. 2006, 14:15

D'abord il faut aranger la requête pour trier les chansons par emissions et dates

En suite il faut lire la requête dans un tableau qui n'enregistre qu'une fois l'emission et la date et qui cumule les noms des artistes dans une même case.

Pour celà et puisque le résultat est trié, la boucle doit affecter les noms des artistes quand l'emission et la date restent inchangées pour former un duo.
En indexant le tableau par emission et date on solutionne le problème des doublons. C'est à dire que dans le même index (emission/date) du tableau on mémorise les noms des artistes sous forme de cumul séparés par un séparateur exemple "&".

N'oublions pas que c'est algorithme traite une seule chanson donnée sous forme de paramètre à la requête de base, il s'agit de $id_chanson.


Solution:
<?php

//Requête qui extrait les DUO d'une chanson donnée par $id_chanson
$id_chanson = $_GET[id_chanson]; //source de l'id_chanson ciblé
if (!$id_chanson) {echo "<p>Aucune chanson n'est sélectionnée!"; exit;}

$sql = "
SELECT i.id_emission, e.nom, i.date, (SELECT nom FROM artiste WHERE i.id_artiste = id) AS nom_artiste 
FROM ( 
      SELECT id_emission, date, id_chanson, if( count( id_artiste ) <2, 'Single', 'Duo' ) AS type 
      FROM interpretation 
      GROUP BY id_emission, date, id_chanson 
) AS types , 
interpretation AS i, emission as e, chanson as c 

WHERE types.type = 'Duo' 
AND i.id_emission = types.id_emission 
AND i.date = types.date 
AND i.id_chanson = types.id_chanson 
AND i.id_emission = e.id 
AND i.id_chanson = c.id

AND i.id_chanson = '$id_chanson'

ORDER BY i.id_emission, i.date, i.id_emission 
";


// on envoie la requête 
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error()); 

// on fait une boucle qui va faire un tour pour chaque enregistrement 

while($data = mysql_fetch_assoc($req)) 
{ 
// on traite les informations de l'enregistrement en cours 
// une chanson => N emission, dont chacune => 2 artistes 
//Pour la même emission/date stocker les noms des artistes séparés par & 
//On va remplir un tableau de duos dont l'index unique est (emmision et date) 
    
//le DUO est enregistré pour la Même emission et même date
   	  $id_emission = $data[id_emission];
   	  $date = $data[date];
      $les_duos [$id_emission][$date][duo] .= $data[nom_artiste]." & " ; //Cumul des noms des duos dans la même case
      //enregistrer aussi les autres infos utiles ex. le nom de l'emission 
      $les_duos [$id_emission][$date][nom_emission]  = $data[nom]; 
 
} 

//Si le tableau des duos est rempli l'afficher 
echo "<p>Le titre <b>$id_chanson</b> a été interprété en Duo par : "; 

if ($les_duos) 
	//Liste des emissions
   foreach ($les_duos as $emissions){ 
   		//sous-liste des dates d'emission
         foreach ($emissions as $date => $data){
		 		//infos emission à une date
		 		$duo = preg_replace("#&$#","", trim($data[duo])); //Elimine le dernier & dans le nom du duo
                echo "<p><b>$duo</b> - Emission diffusée le ($date)"; 
        } 
     }
//Liste vide 
else echo "<p>Personne!";
?>
Exécuté par l'url: http: //localhost/artistes&chansons/duo.php?id_chanson=1
Ce programme affiche le résultat suivant :
  • Le titre 1 a été interprété en Duo par :

    Don VOORHEES & Paul WHITEMAN - Emission diffusée le (1928-01-07 00:00:00)

    JOHNTONE & LAYTON - Emission diffusée le (1928-05-10 00:00:00)
Conformement au jeu d'enregistrements contenu dans la base de données (voir mon post précédent)
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Invité
Invité n'ayant pas de compte PHPfrance

15 févr. 2006, 19:05

Merci une fois de plus. Ton script fonctionne mais par contre j'ai plein de messages d'erreur du style:

Notice: Use of undefined constant id_chanson - assumed 'id_chanson' in....

Notice: Use of undefined constant date - assumed 'date' in...

Lorsque j'avais ces erreurs jusqu'à présent c que je m'étais trompé dans le nommage des champs mais là ça n'a pas l'air d 'être le cas.

Une idée ?

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

16 févr. 2006, 09:35

C'est pas grave, tu dois mettre ces noms entre guillemets ou quotes puisqu'il s'agit d'index de tableau.

Exemple: $data[id_emission]; devient : $data['id_emission'];

Ceci est vrai pour tous les tableaux y compri $_GET.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

ViPHP
ViPHP | 2144 Messages

16 févr. 2006, 11:26

Perso, j'aurai dissocier l'interprétation d'une chanson et la participation d'un artiste:
une table interprétation qui reprend les informations propres à l'interprétation:
idInterpreation, idChanson, idEmission

et une table participation:
idInterpretation, idArtiste.

Sans cela, je pense qu'il y a un risque de problême, si (ça peut toujours arrivé) une même chanson a deux interprétations différentes dans la même émission, avec des artistes différents. En plus ça évites une redondances des données propres à l'interprétation.

Invité
Invité n'ayant pas de compte PHPfrance

21 févr. 2006, 16:27

Re.

J'ai bien suivi tes conseils. Malheureusement, j'ai toujours quelques messages d'erreur. Je te remets le code corrigé à tout hasard, ainsi que les erreurs que j'obtiens.
<HTML><HEAD><TITLE>Recherchez un titre de chanson interprété à Taratata</TITLE>
  
</HEAD>
<BODY>


<? if(!empty($_POST["titre_chanson"])) { ?>
   Voici les artistes qui ont chanté en Duo ou à plusieurs une chanson dont le titre comprend le(s) mot(s) <b><? echo 

$_POST["titre_chanson"]; ?></b> :
   <br><br>
<? } ?>



<?php 


// on se connecte à MySQL 
$db = mysql_connect('localhost', 'root', ''); 

// on sélectionne la base 
mysql_select_db('ta..',$db); 




//Requête qui extrait les DUO d'une chanson donnée par $id_chanson

$id_chanson = $_GET['id_chanson']; //source de l'id_chanson ciblé 
if (!$id_chanson) {echo "<p>Aucune chanson n'est sélectionnée!"; exit;} 

$sql = " 
SELECT i.id_emission, e.nom, i.date, (SELECT nom FROM artiste WHERE i.id_artiste = id) AS nom_artiste 
FROM ( 
      SELECT id_emission, date, id_chanson, if( count( id_artiste ) <2, 'Single', 'Duo' ) AS type 
      FROM interpretation 
      GROUP BY id_emission, date, id_chanson 
) AS types , 
interpretation AS i, emission as e, chanson as c 

WHERE types.type = 'Duo' 
AND i.id_emission = types.id_emission 
AND i.date = types.date 
AND i.id_chanson = types.id_chanson 
AND i.id_emission = e.id 
AND i.id_chanson = c.id 

AND i.id_chanson = '$id_chanson' 

ORDER BY i.id_emission, i.date, i.id_emission 
"; 


// on envoie la requête 
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error()); 

// on fait une boucle qui va faire un tour pour chaque enregistrement 

while($data = mysql_fetch_assoc($req)) 
{ 
// on traite les informations de l'enregistrement en cours 
// une chanson => N emission, dont chacune => 2 artistes 
//Pour la même emission/date stocker les noms des artistes séparés par & 
//On va remplir un tableau de duos dont l'index unique est (emmision et date) 
     
//le DUO est enregistré pour la Même emission et même date 
         $id_emission = $data['id_emission']; 
         $date = $data['date']; 
      $les_duos [$id_emission]['$date']['duo'] .= $data['nom_artiste']." & " ; //Cumul des noms des duos dans la même case 
      //enregistrer aussi les autres infos utiles ex. le nom de l'emission 
      $les_duos [$id_emission][$date]['nom_emission']  = $data['nom']; 

} 

//Si le tableau des duos est rempli l'afficher 
echo "<p>Le titre <b>$id_chanson</b> a été interprété en Duo par : "; 

if ($les_duos) 
    //Liste des emissions 
   foreach ($les_duos as $emissions){ 
           //sous-liste des dates d'emission 
         foreach ($emissions as $date => $data){ 
                 //infos emission à une date 
                 $duo = preg_replace("#&$#","", trim($data['duo'])); //Elimine le dernier & dans le nom du duo 
                echo "<p><b>$duo</b> - Emission diffusée le ($date)"; 
        } 
     } 
//Liste vide 
else echo "<p>Personne!"; 



// on ferme la connexion à mysql 
mysql_close(); 
?> 


</body></html>


Les erreurs sont les suivantes :
Notice: Undefined variable: les_duos in c:\documents and settings\developpement.air\bureau\mou\sql4.php on line 68

Notice: Undefined index: 5 in c:\documents and settings\developpement.air\bureau\mou\sql4.php on line 68

Notice: Undefined index: $date in c:\documents and settings\developpement.air\bureau\mou\sql4.php on line 68

Notice: Undefined index: duo in c:\documents and settings\developpement.air\bureau\mou\sql4.php on line 68

Le titre 1 a été interprété en Duo par :

LAYTON & MouMou & JOHNTONE - Emission diffusée le ($date)
Notice: Undefined index: duo in c:\documents and settings\developpement.air\bureau\mou\sql4.php on line 83


- Emission diffusée le (1928-05-10 00:00:00)

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

27 févr. 2006, 13:53

C'est un problème d'index nommés dans les tableaux.

Tu peux utiliser un nom d'index sans quillemets ou apostrohes, mais si tu utilise un délimiteur péréfére les guillemets. et évite la fome :
$tableau['$variable'] car l'apostrophe hénibe l'effet de la variable $
préfère $tableau["$variable"]

En disant ça je pense à l'index ['$date'] dans ton code qui provoque l'erreur telqu'il est formulé. Ecrit plutôt ["$date"]

Selon ton parser, la variable $les_duos n'est pas initialisée pour supporter la concaténation dans la boucle, c'est juste une notice et non une erreur.
Initialise cette variable avant la boucle:
$les_duos = array();
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène