I am having problems trying to view some data and wondered if anyone could help.
I have a table called ‘parties’ which contains fields - partyid, docid and party. There is another table called ‘documents’ which has fields - docid and doctitle.
I have a number of documents and for each document there are a number of parties - ie people linked to that document.
What I would like to do is get a view on screen (and also printed out) that has the title of the document followed by a list of the parties associated with that document.
// Database connection goes here
$query = "
SELECT
doctitle
, party
FROM documents
INNER JOIN parties
ON documents.docid = parties.docid
";
$result = mysql_query($query) or die("mysql error : " . mysql_error() . " in query $query");
// load the query result in a bidimensional array
$list = array();
while ($row = mysql_fetch_array($result)) {
$list[$row['doctitle']][] = $row['party'];
}
// let's display the list to see the result
// (it's just for demonstration purposes, you can eliminate it after you've checked it)
print_r($list);
// loop through the array to create the list
foreach ($list as $document => $parties) {
echo $document . "<br />";
foreach ($parties as $party) {
echo $party . "<br />";
}
echo "<br />";
}
I’ll assume that Fred #1 is different from Fred #5. Your query will become:
<?php
$query = "
SELECT doctitle, documents.docid, party, partyid
FROM documents
INNER JOIN parties ON documents.docid = parties.docid
ORDER BY doctitle, docid, party, partyid
";
?>
Notice how ORDER clause is used. Now you can display the results, grouped, as follows:
<?php
$docid = -1; // initialize with -1 (see reason below)
$result = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($result)) { // group and display rows in one go
if($docid != $row["docid"]) { // if we have not yet displayed the header for current docid
$docid = $row["docid"]; // display and make a note that it has been displayed
?>
<h1><?php echo $row["doctitle"]; ?> (id #<?php echo $row["docid"]; ?>)</h1>
<?php
}
?>
<p><?php echo $row["party"]; ?> (id #<?php echo $row["partyid"]; ?>)</p>
<?php
}
?>
Let me make my own assumption, since we’re all doing it…
The key on the table is (partyid) PRIMARY auto_increment, natural key is (docid,party) UNIQUE
Which would mean:
The table is redundant (You should make a users table and link the id into the join table, rather than saving each person’s name over and over)
Sorting by Doctitle and then docid is redundant unless the user has allowed two documents to have the same name; sorting by doctitle is assuming the OP’s intent, as it is purely cosmetic. Sorting by party and then partyid is redundant because of the natural key.
The queries also offered above are operating on the assumption that you want to pull ALL documents on a single page. Is that the intent, or are you trying to select a singular document?
Many thanks for the suggestions - I am just about to start trying them.
I have moved on a little bit and both the documents and parties tables contain a field ‘idcode’ which also links to other tables which are not used for this example. However, a single idcode could be linked to several documents.
For example:
the documents table entries might be
|docid |doctitle |idcode
|1 |first document |1234
|2 |second document|1234
|3 |third document |3456
So, for a particular idcode (which is carried with the url) I can list the document title and its parties in the format (for example when idcode=1234):
First document:
Fred
Jim
Jane
Second document:
Peter
Fred
I do want to pull all of the documents (with the same idcode) on a single page but some parties will be the same for different documents. In my example Fred is the same party - he is linked to 2 separate documents.
Okay. Understanding it better now. You’ve got some redundancy, so lets try and clear that up first.
Schema:
Party
partyid
name
Documents
docid
idcode
doctitle
party_doc
docid
partyid
$query = "SELECT document.doctitle,GROUP_CONCAT(party.name ORDER BY party.name SEPARATOR '<br>') AS names
FROM document
LEFT JOIN party_doc ON document.docid = party_doc.docid
INNER JOIN party ON party_doc.partyid = partyid
WHERE document.idcode = ".$idcode;
$res = $sql->query($query);
while($row = $res->fetch_array()) {
echo $row['doctitle'].":<br>".$row['names'];
}
Ok, in that case the database layout posted by StarLion is the way to go.
As far as the query is concerned, you can use his GROUP_CONCAT solution, or use mine (see answer #3) with some modification (you’ll have to join 3 tables).