Problem with joins and listing

Hallo,
I’m struggeling with some table joins and listings. I have managed to output a list but when it’s supposed to show a list of artists and curators it duplicates the exhibit name for each artist. I have tried to make it work as with the gallery name (saveName) but it’s not making any difference.
I’m not sure if that’s the answer, maybe it’s in the SELECT and JOINS? Or should it be a count of artists with a FOREACH inside the result array?
Here is what I’m looking for:

Gallery name1
Gallery adress, etc.
dates exhibit name1: Artist: artist1, artist2, artist3. Kurator: curator1. Info: some info
dates exhibit name2: Artist: artist1, artist2. Kurator: curator 1, etc.

Gallery name2
Gallery adress, etc.
dates exhibit name1: Artist: artist1, artist2, artist3. Kurator: curator 1
etc.

Any help would be greatly appreciated.

// View of gallery, exhibits and partisipants in tables
$row = 1;
$saveName = '';
$saveTitle = '';
$result = mysql_query( 
    "SELECT p.id
        , p.title
        , p.info
        , p.galleryid
        , p.start_date
        , p.end_date
        , p.date
        , c.id
        , c.galleryname 
        , c.address 
        , a.aname
        , a.exhibitid 
        , k.cname
        , k.exhibitid 
        FROM exhibit AS p
		LEFT JOIN artist AS a ON p.id=a.exhibitid
		LEFT JOIN curator AS k ON p.id=k.exhibitid
        INNER JOIN gallery AS c 
        ON p.galleryid=c.id
		ORDER BY c.galleryname, p.start_date" );

while($list = mysql_fetch_array($result)) {
	$gname = $list['galleryname'];
	$adr = $list['address'];
  $start = $list['start_date'];
  $end = $list['end_date'];
  $timestamp = strtotime($start);
  $start = date("d.m.y",$timestamp);
  $timestamp = strtotime($end);
  setlocale(LC_TIME, "no_NO.ISO_8859-1");
  $end = date("d.m.y",$timestamp);
  $title = $list['title'];
  $info = $list['info'];
  $date = $list['date'];
  $timestamp = strtotime($date);
  $date = date("d.m.y",$timestamp);
  setlocale(LC_TIME, "no_NO.ISO_8859-1");
  $art = $list['aname'];
  $cur = $list['cname'];

  if ($gname != $saveName && $title != $saveTitle) {

    $result_array[] = "<table class='galleryname'><tr><td class='gname'>$gname</td></tr><tr><td class='gen'>$adr</td></tr></table><table class='exh'><tr><td class='dato'>$start - $end ($date)</td><td class='title'>".$list['title'].", " . $list['aname'] . ", kurator: $cur</td><td class='info'>$info</td></tr></table>"; 
    $saveName = $gname;            
    $saveTitle = $title;            
  	} else {
    $result_array[] = "<table class='exh'><tr><td class='dato'>$start - $end ($date)</td><td class='title'>".$list['title'].",  " . $list['aname'] . ", kurator: $cur</td><td class='info'>$info</td></tr></table>";
  	}
}

$result_final = "<table class='list'><tr>\
";
foreach($result_array as $cvtext) {
  if($counter == $row) {    
    $counter = 1;
    $result_final .= "\
</tr>\
<tr>\
";
  }
  else $counter++;
  $result_final .= "\	<td>" . $cvtext . "</td>\
";
}
if($counter) {
  if($rows) $result_final .= "\	<td colspan='".($row-$counter)."'></td>\
";
  $result_final .= "</tr></table>";
}
echo $result_final;

May I ask why you are using tables inside tables inside… ? I tried to follow the logic, but I gave up.
In theory, you should do something like this, how to implement it in your code is something you’ll have to find out yourself :slight_smile:

// initialize the variables used for checking any changes
$saveName = ''; 
$saveTitle = ''; 

while ($list = mysql_fetch_array($result)) { 
  // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
  if ($list['galleryname'] != $saveName) {      
    // display gallery info
    ...
    // save new gallery name  
    $saveName = $list['galleryname'];
  } 

  // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name
  if ($list['title'] != $saveTitle) {      
    // display exhibit info
    ...
    // save new exhibit name  
    $saveTitle = $list['title'];
  } 
  
  // display all other info
  ...
}  

Thanks Guido,

I’m not sure what you mean with tables inside tables.
I have a table for galleries. Each gallery can have several exhibits and each exhibit can have one or more artist and one or more curator. That’s four tables related by internal and external IDs.
Could I have done it differently?

I’ll try to work out your code:-)

This is a link to the listing by now:
LISTEN - Utstillingsoversikt
As you can see every exhibit repeats itself for each artist.

I’m lost with this.
How do I collect the different gallery, exhibit and “rest” displays from the loop into one $result_array?
Can someone please give me a hint.
Thanks!

Guido is talking about how you are nesting tables within tables so:


<table>
 <tr>
  <td>
   <table>
    ...
   </table>
  </td>
 </tr>
</table>

I would start with the code he gave you.

Ahh those tables… That’s something I havn’t looked at yet, I’m more conserned about the data output:)
I’m not going to use tables in the end, it was just some code I had.

It’s what he suggested I’m not getting. I need all in a $result_array, right? But how can I put all the different output together and have one $result_array?

I tried this but it didn’t work:


// initialize the variables used for checking any changes
$saveName = '';
$saveTitle = '';
 
while ($list = mysql_fetch_array($result)) { 
  // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
  if ($list['galleryname'] != $saveName) {      
    // display gallery info
    $gallery = "<table class='galleryname'><tr><td class='gname'>$gname</td></tr><tr><td class='gen'>$adr, $zip $city, $tel, $url</td></tr></table>"; 
    // save new gallery name  
    $saveName = $list['galleryname'];
  } 
  // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name
  if ($list['title'] != $saveTitle) {      
    // display exhibit info
   $exhibit = "<table class='exh'><tr><td class='dato'>$start - $end ($date)</td><td class='title'>$title</td><td class='title'>".$list['aname']."</td><td class='info'>$info</td></tr></table>"; 
    // save new exhibit name  
    $saveTitle = $list['title'];
  } 
  // display all other info
    $rest = "<table class='exh'><tr><td class='title'>".$list['aname']."</td></tr></table>";
}

$result_array[] = "$gallery<br />$exhibit $rest";
}

$result_final = "<table class='list'><tr>\
";
foreach($result_array as $galleries) {
  if($counter == $row) {    
    $counter = 1;
    $result_final .= "\
</tr>\
<tr>\
";
  }
  else $counter++;
  $result_final .= "\	<td>" . $galleries . "</td>\
";
}
if($counter) {
  if($rows) $result_final .= "\	<td colspan='".($row-$counter)."'></td>\
";
  $result_final .= "</tr></table>";
}
echo $result_final;

Get rid of them right now, they’re complicating things.

I need all in a $result_array, right?

That depends. Looking at your site right now, it seems you want to put the info at the end. If it was displayed at the beginning (like time and exhibit name) then it could be placed inside the second if (that displays exhibit info) and you could display the data without loading it in an array first.
If it has to be at the end, then you’ll have to load the data in an array first (but without html markup, just the data) and then loop through that array to create the output the way you want it.

I tried this but it didn’t work:

What does ‘didn’t work’ mean?

  // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name
  if ($list['title'] != $saveTitle) {      
    // display exhibit info
   $exhibit = "<table class='exh'><tr><td class='dato'>$start - $end ($date)</td><td class='title'>$title</td><td class='title'>".$list['aname']."</td><td class='info'>$info</td></tr></table>"; 
    // save new exhibit name  
    $saveTitle = $list['title'];
  } 
  // display all other info
    $rest = "<table class='exh'><tr><td class='title'>".$list['aname']."</td></tr></table>";
}

You are displaying the ‘aname’ twice: once in the exhibit info part, and once in the ‘all other info’ part.

I have removed the top tables and replaced with span.
When I said it didn’t work I meant I only got one gallery with one exhibit. And the artist was from a totally different exhibit and gallery.
The info text concerns the exhibit so it can stay after the exhibit name.
LISTEN - Utstillingsoversikt
Here is the changed code:


// initialize the variables used for checking any changes
$saveName = '';
$saveTitle = '';
 
while ($list = mysql_fetch_array($result)) { 
  // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
  if ($list['galleryname'] != $saveName) {      
    // display gallery info
    $gallery = "<p><span class='gname'>$gname</span><br /><span class='general'>$adr, $zip $city, $tel, $url</span></p>"; 
    // save new gallery name  
    $saveName = $list['galleryname'];
  } 
  // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name
  if ($list['title'] != $saveTitle) {      
    // display exhibit info
   $exhibit = "<span class='date'>$start - $end ($date) </span><span class='title'>$title </span>"; 
    // save new exhibit name  
    $saveTitle = $list['title'];
  } 
  // display all other info
    $rest = "<span class='participants'>".$list['aname'].",</span><span class='info'>$info</span>";
}

$result_array[] = "$gallery<br />$exhibit $rest";
}

$result_final = "<table class='list'><tr>\
";
foreach($result_array as $galleries) {
  if($counter == $row) {    
    $counter = 1;
    $result_final .= "\
</tr>\
<tr>\
";
  }
  else $counter++;
  $result_final .= "\	<td>" . $galleries . "</td>\
";
}
if($counter) {
  if($rows) $result_final .= "\	<td colspan='".($row-$counter)."'></td>\
";
  $result_final .= "</tr></table>";
}
echo $result_final;


 // initialize the variables used for checking any changes 
$saveName = ''; 
$saveTitle = '';   
while ($list = mysql_fetch_array($result)) { 
   $gallery = '';
   $exhibit = '';
   // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
   if ($list['galleryname'] != $saveName) {
     // display gallery info
     $gallery = "<p><span class='gname'>$gname</span><br /><span class='general'>$adr, $zip $city, $tel, $url</span></p>";
     // save new gallery name  
     $saveName = $list['galleryname'];
   }
   // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name 
   if ($list['title'] != $saveTitle) {  
     // display exhibit info
     $exhibit = "<span class='date'>$start - $end ($date) </span><span class='title'>$title </span><span class='info'>$info</span>";  
     // save new exhibit name  
     $saveTitle = $list['title'];
   } 
   // display all other info  
   $result_array[] = "$gallery<br />$exhibit <span class='participants'>".$list['aname'].",</span>"; 
}   

Tried this and the first gallery and first exhibit repeats itself for everyone.
But the artists changes.

This is how it is now:
LISTEN - Utstillingsoversikt 3

This is all the correct galleries and exhibits, except only one artist (and earlier design):
LISTEN - Utstillingsoversikt

(FYI! The list is a gallery listing for a book/catalogue. It will be proofread later)

Did you add these two lines?


while ($list = mysql_fetch_array($result)) { 
[B][COLOR="Red"]
   $gallery = '';
   $exhibit = '';[/COLOR][/B]   
   // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
   if ($list['galleryname'] != $saveName) {

And of course, I never post all those lines that assign the $list data to the variables like $gname, but since you still use them I presume you still have these lines inside the while-loop.

I just changed the part in your post.

// initialize the variables used for checking any changes
$saveName = ''; 
$saveTitle = '';   
while ($list = mysql_fetch_array($result)) { 
   $gallery = '';
   $exhibit = '';
   // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
   if ($list['galleryname'] != $saveName) {
     // display gallery info
     $gallery = "<p><span class='gname'>$gname</span><br /><span class='general'>$adr, $zip $city, $tel, $url</span></p>";
     // save new gallery name  
     $saveName = $list['galleryname'];
   }
   // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name 
   if ($list['title'] != $saveTitle) {  
     // display exhibit info
     $exhibit = "<span class='date'>$start - $end ($date) </span><span class='title'>$title </span><span class='info'>$info</span>";  
     // save new exhibit name  
     $saveTitle = $list['title'];
   } 
   // display all other info  
   $result_array[] = "$gallery<br />$exhibit <span class='participants'>".$list['aname'].",</span>"; 
}
}

Strange, so the gallery changes, and you’ve emptied $gallery at the beginning of the loop, and at the end it has the same value as the first gallery. Very strange.
Can you post the complete code, that is from the query onwards, like you did in your OP?

I wonder about the two braces after the loop. Should both be there or shoud the last one actually be after the final echo?
Here is he code:

// initialization
$result_array = array();
$counter = 0;

// View of cv content in tables
$row = 1;
$result = mysql_query( 
    "SELECT p.id
        , p.title
        , p.info
        , p.galleryid
        , p.start_date
        , p.end_date
        , p.date
        , c.id
        , c.galleryname 
        , c.address 
        , c.zip 
        , c.city 
        , c.telephone 
        , c.url 
        , c.email 
        , a.aname
        , a.exhibitid 
        , k.cname
        , k.exhibitid 
        FROM exhibit AS p
		LEFT JOIN artist AS a ON p.id=a.exhibitid
		LEFT JOIN curator AS k ON p.id=k.exhibitid
        INNER JOIN gallery AS c 
        ON p.galleryid=c.id
		ORDER BY c.galleryname, p.start_date" );

while($list = mysql_fetch_array($result)) {
	$gname = $list['galleryname'];
	$adr = $list['address'];
	$zip = $list['zip'];
	$city = $list['city'];
	$tel = $list['telephone'];
	$url = $list['url'];
	$mail = $list['email'];
  $start = $list['start_date'];
  $end = $list['end_date'];
  $timestamp = strtotime($start);
  $start = date("d.m.y",$timestamp);
  $timestamp = strtotime($end);
  setlocale(LC_TIME, "no_NO.ISO_8859-1");
  $end = date("d.m.y",$timestamp);
  $title = $list['title'];
  $info = $list['info'];
  $date = $list['date'];
  $timestamp = strtotime($date);
  $date = date("d.m.y",$timestamp);
  setlocale(LC_TIME, "no_NO.ISO_8859-1");
	$art = $list['aname'];
	$cur = $list['cname'];

// initialize the variables used for checking any changes
$saveName = ''; 
$saveTitle = '';   
while ($list = mysql_fetch_array($result)) { 
   $gallery = '';
   $exhibit = '';
   // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
   if ($list['galleryname'] != $saveName) {
     // display gallery info
     $gallery = "<p><span class='gname'>$gname</span><br /><span class='general'>$adr, $zip $city, $tel, $url</span></p>";
     // save new gallery name  
     $saveName = $list['galleryname'];
   }
   // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name 
   if ($list['title'] != $saveTitle) {  
     // display exhibit info
     $exhibit = "<span class='date'>$start - $end ($date) </span><span class='title'>$title </span><span class='info'>$info</span>";  
     // save new exhibit name  
     $saveTitle = $list['title'];
   } 
   // display all other info  
   $result_array[] = "$gallery<br />$exhibit <span class='participants'>".$list['aname'].",</span>"; 
}
} // here?
$result_final = "<table class='list'><tr>\
";
foreach($result_array as $galleries) {
  if($counter == $row) {    
    $counter = 1;
    $result_final .= "\
</tr>\
<tr>\
";
  }
  else $counter++;
  $result_final .= "\	<td>" . $galleries . "</td>\
";
}
if($counter) {
  if($rows) $result_final .= "\	<td colspan='".($row-$counter)."'></td>\
";
  $result_final .= "</tr></table>";
}
echo $result_final;
// or here?

When I changed all the variables in the loop it got right:)
But for some reason the first artist in the first exhibit for the first gallery is missing.
And some artists are listed twice and three times for some exhibits.

Is there a way to convert dates using these variables instead of the short one?

// initialize the variables used for checking any changes
$saveName = ''; 
$saveTitle = '';   
while ($list = mysql_fetch_array($result)) { 
   $gallery = '';
   $exhibit = '';
   // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
   if ($list['galleryname'] != $saveName) {
     // display gallery info
     $gallery = "<p><span class='gname'>".$list['galleryname']."</span><br /><span class='general'>".$list['address'].", ".$list['zip']." ".$list['city'].", ".$list['telephone'].", ".$list['url']."</span></p>";
     // save new gallery name  
     $saveName = $list['galleryname'];
   }
   // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name 
   if ($list['title'] != $saveTitle) {  
     // display exhibit info
     $exhibit = "<span class='date'>".$list['start_date']." - ".$list['start_date']." (".$list['date'].") </span><span class='title'>".$list['title']." </span><span class='info'>".$list['info']." <br /></span>";  
     // save new exhibit name  
     $saveTitle = $list['title'];
   } 
   // display all other info  
   $result_array[] = "$gallery<br />$exhibit <span class='participants'>".$list['aname'].",</span>"; 
}

I managed to fix the things mentioned above, but I have another question. Is it possible to group artists and curators? As it looks now the curator(s) comes after the first artist and then comes the next artist on another line. And then the curator(s) repeats for each artist. I was hoping I could list the artists with commas and then list the curator(s) with commas. Like this: artist1, artist2, artist3 Curator: curator1, curator2
Here’s the code:

// initialization
$result_array = array();
$counter = 0;

// View of cv content in tables
$row = 1;
$result = mysql_query( 
    "SELECT p.id
        , p.title
        , p.info
        , p.galleryid
        , p.start_date
        , p.end_date
        , p.date
        , c.id
        , c.galleryname 
        , c.address 
        , c.zip 
        , c.city 
        , c.telephone 
        , c.url 
        , c.email 
        , a.aname
        , a.exhibitid 
        , k.cname
        , k.exhibitid 
        FROM exhibit AS p
		LEFT JOIN artist AS a ON p.id=a.exhibitid
		LEFT JOIN curator AS k ON p.id=k.exhibitid
        INNER JOIN gallery AS c 
        ON p.galleryid=c.id
		ORDER BY c.galleryname, p.start_date" );
$saveName = ''; 
$saveTitle = '';   
$saveArtist = '';   
$saveCurator = '';   

// initialize the variables used for checking any changes
while ($list = mysql_fetch_array($result)) { 
   $gallery = '';
   $exhibit = '';
   $artists = '';
   $curators = '';
	$gname = $list['galleryname'];
	$adr = $list['address'];
	$zip = $list['zip'];
	$city = $list['city'];
	$tel = $list['telephone'];
	$url = $list['url'];
	$mail = $list['email'];
  $title = $list['title'];
  $info = $list['info'];
  $date = $list['date'];
  $timestamp = strtotime($date);
  $date = date("d.m.y",$timestamp);
  setlocale(LC_TIME, "no_NO.ISO_8859-1");
	$art = $list['aname'];
	$cur = $list['cname'];
  $start = $list['start_date'];
  $end = $list['end_date'];
  $timestamp = strtotime($start);
  $start = date("d.m.y",$timestamp);
  $timestamp = strtotime($end);
  setlocale(LC_TIME, "no_NO.ISO_8859-1");
  $end = date("d.m.y",$timestamp);

   // check if the gallery has changed. If it did, display the gallery info and save the new gallery name
   if ($list['galleryname'] != $saveName) {
     // display gallery info
     $gallery = "<p><span class='gname'>".$list['galleryname']."</span><br /><span class='general'>".$list['address'].", ".$list['zip']." ".$list['city'].", ".$list['telephone'].", ".$list['url']."</span></p>";
     // save new gallery name  
     $saveName = $list['galleryname'];
   }
   // check if the exhibit name has changed. If it did, display the exhibit info and save the new exhibit name 
   if ($list['title'] != $saveTitle) {  
     // display exhibit info
     $exhibit = "<span class='date'>$start - $end ($date) </span><span class='title'>".$list['title']." </span><span class='info'>".$list['info']." <br /></span>";  
     // save new exhibit name  
     $saveTitle = $list['title'];
   } 
   if ($list['aname'] != $saveArtist) {  
   // display all other info  
   $artists = "<span class='participants'>".$list['aname'].",</span>"; 
     $saveArtist = $list['aname'];
   }
   if ($list['cname'] != $saveCurator) {  
   // display all other info  
   $curators = "<span class='participants'>kurator: ".$list['cname'].",</span>"; 
     $saveCurator = $list['cname'];
   }
   $result_array[] = "$gallery$exhibit $artists $curators"; 
}

$result_final = "<div id='gallery'>";
foreach($result_array as $galleries) {
  if($counter == $row) {    
    $counter = 1;
    $result_final .= "</div><div>";
  }
  else $counter++;
  $result_final .= "$galleries";
}
if($counter) {
  if($rows) $result_final .= "$row-$counter";
  $result_final .= "</div>";
}
echo $result_final;

Here is the link to the page:
LISTEN - Utstillingsoversikt 3
Thanks!

A inner join following a left join will turn the left joins into an inner – that isn’t the solution to your current problem but its worth mentioning. How many artists, curators and galleries does a exhibit have? You also need to add some aliases your columns that have the same name to differentiate them in the result set ie. – p.id,c.id.

Thanks for the info about joins. I don’t think it matters in this case since the inner join between gallery and exhibit is sufficient. No exhibit => no artists or curators? I hope…:slight_smile: At least as the output is correct…
Each exhibit must have at least one artist or as many as they want to submit. It doesn’t need to have any curators at all/or as many as wanted.
Regarding the aliases I don’t see that any of the fields used have the same name except ‘exhibitid’ which in this case has the same value (and different aliases). Or do I misunderstand what you mean?