我在MySQL中有以下两个表结构,它记录了电话会议的详细信息以及加入它的参与者:
表:会议:
conference_sid, date_created, date_completed, RecordURL, PIN
* date_created和* date_completed是时间戳
表:参与者:
conference_sid, call_sid, call_from, name_recording
我想输出一个简单的表,它将每个conference_sid的以下结果显示为一个单独的行:
<table>
<thead>
<th>Date</th>
<th>Duration</th>
<th>Participants</th>
<th>Recording</th>
</thead>
<tbody>
<tr id="conference_sid">
<td>date_created</td>
<td>duration: [date_completed - date_created in h/mm/ss]</td>
<td>
<li><a href="name_recording">call_from</a> [for all participants in that conference_sid]
<li>call_from...
</td>
<td>
<a href="RecordURL">Call recording</a>
</td>
</tr>
<tr id="conference_sid">
...
</tr>
</tbody>
</table>
我只希望此表显示与用户的Session :: get('PIN')具有相同PIN的会议的相关结果
答案 0 :(得分:4)
您可以使用GROUP_CONCAT
组合参与者SELECT
conf.conference_sid,
date_created,
TIMEDIFF(date_completed, date_created) AS duration,
conf.RecordURL,
conf.PIN,
GROUP_CONCAT(pid SEPARATOR ",") AS pid,
GROUP_CONCAT(call_sid SEPARATOR ",") AS call_sid,
GROUP_CONCAT(call_from SEPARATOR ",") AS call_from,
GROUP_CONCAT(name_recording SEPARATOR ",") AS name_recording
FROM
conference conf
LEFT OUTER JOIN
participants p ON p.conference_sid = conf.conference_sid
WHERE
conf.PIN = 123
GROUP BY conf.conference_sid
请参阅有关SQLFIDDLE的TIMEDIFF和MySQL文档。
现在应用程序逻辑将是
<?php
$pin = 123;
$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$stmt = $db->prepare(
'SELECT
conf.conference_sid,
date_created,
timediff(date_completed, date_created) AS duration,
conf.RecordURL,
conf.PIN,
GROUP_CONCAT(pid SEPARATOR ",") AS pid,
GROUP_CONCAT(call_sid SEPARATOR ",") AS call_sid,
GROUP_CONCAT(call_from SEPARATOR ",") AS call_from,
GROUP_CONCAT(name_recording SEPARATOR ",") AS name_recording
FROM
conference conf
LEFT OUTER JOIN
participants p ON p.conference_sid = conf.conference_sid
WHERE
conf.PIN = :pin
GROUP BY conf.conference_sid');
$stmt->bindParam(':pin', $pin);
?>
<table border="1">
<thead>
<th>Date</th>
<th>Duration</th>
<th>Participants</th>
<th>Recording</th>
</thead>
<tbody>
<?php
$stmt->execute();
while ($row = $stmt->fetch()) {
?>
<tr>
<td><?php echo $row['date_created']; ?></td>
<td><?php echo $row['duration']; ?></td>
<td>
<table border="1">
<thead>
<th>call_sid</th>
<th>call_from</th>
<th>name_recording</th>
</thead>
<tbody>
<?php
$length = count(explode(',', $row['pid']));
$call_sid = explode(',', $row['call_sid']);
$call_from = explode(',', $row['call_from']);
$name_recording = explode(',', $row['name_recording']);
for ($i=0; $i < $length; $i++) {
?>
<tr>
<td> <?php echo $call_sid[$i]; ?> </td>
<td> <?php echo $call_from[$i]; ?></td>
<td> <?php echo $name_recording[$i]; ?> </td>
<tr>
<?php
}
?>
</tbody>
</table>
</td>
<td>
<a href="<?php echo $row['RecordURL']; ?>">
Call recording</a>
</td>
</tr>
<?php
}
?>
</tbody>
您将在pid,call_sid,call_from和name_recording中使用逗号(,)分隔值获取结果集。您可以使用explode将此字符串转换为数组。
array explode ( string $delimiter , string $string [, int $limit ] )
返回一个字符串数组,每个字符串都是字符串的子字符串 通过将其分割成由字符串分隔符形成的边界而形成。
答案 1 :(得分:2)
我不会做PHP部分,因为我不熟悉PHP,但这里是SQL:
SELECT *
FROM `conference`, `participants`
WHERE `conference`.PIN = $PIN AND
`participants`.conference_sid = `conference`.conference_sid
这将返回包含来自conference
的信息和participants
conferences
的信息的行,这些信息会合并为一行。
答案 2 :(得分:0)
以下查询将为您提供显示所需的信息:
SELECT c.conference_sid
, c.date_created
, timediff(c.date_completed, c.date_created) AS duration
, p.call_from
, p.name_recording
, c.RecordURL
FROM conference c
JOIN participants p
ON c.conference_sid = p.conference_sid
WHERE c.PIN = :PIN
ORDER BY c.conference_sid
您需要使用嵌套循环处理结果。每次conference_sid
更改时,外循环都应该前进。内部循环将显示该会议的参与者列表的每个元素。
答案 3 :(得分:0)
在这个特定的上下文中,我更喜欢使用两个独立的查询。以下是我将如何做到这一点:
<?php
try {
$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Could not connect to db';
exit;
}
$stmt_conferences = $db->prepare(
'SELECT
date_created,
timediff(date_completed, date_created) AS duration,
RecordURL,
conference_sid
FROM
conference
WHERE
PIN=:pin');
$stmt_conferences->bindParam(':pin', $pin);
$stmt_participants = $db->prepare(
'SELECT
name_recording,
call_from
FROM
participants
WHERE
conference_sid=:confsid');
$stmt_participants->bindParam(':confsid', $confsid);
?>
<table>
<thead>
<th>Date</th>
<th>Duration</th>
<th>Participants</th>
<th>Recording</th>
</thead>
<tbody>
<?php
$pin = 1; /* get your PIN here */
$stmt_conferences->execute();
while ($row = $stmt_conferences->fetch()) {
?>
<tr>
<td><?php echo htmlspecialchars($row['date_created'], ENT_QUOTES); ?></td>
<td><?php echo htmlspecialchars($row['duration'], ENT_QUOTES); ?></td>
<td>
<?php
$confsid = $row['conference_sid'];
$stmt_participants->execute();
while ($participant = $stmt_participants->fetch()) {
?>
<li><a href="<?php echo htmlspecialchars($participant['name_recording'], ENT_QUOTES); ?>">
<?php echo htmlspecialchars($participant['call_from'], ENT_QUOTES); ?>
</a>
<?php
}
?>
</td>
<td>
<a href="<?php echo htmlspecialchars($row['RecordURL'], ENT_QUOTES); ?>">
Call recording</a>
</td>
</tr>
<?php
}
?>
</tbody>
请注意,您必须添加一些代码来处理错误并正确转义您回显的所有数据(您真的可以信任您的数据库吗?)。此外,元素ID在整个文档中应该是唯一的,您的页面中只能有一个id="conference_sid"
。改为使用类。
修改强>
如果您真的可以信任您的数据库,那么您可以使用以下代码输出字段的内容:
<?php echo $row['call_from']; ?>
但是如果RecordURL包含例如以下字符串会发生什么?
<script>alert("I am injecting some code....");</script>
将会在页面中注入一些不需要的代码,因此每次需要回显一些输出时,最好使用像htmlspecialchars()这样的安全函数:
<?php echo htmlspecialchars($row['call_from'], ENT_QUOTES); ?>
这样,任何不需要的代码都不会有害。
我还为handle errors添加了一个基本的TRY / CATCH构造。
希望这有帮助!
答案 4 :(得分:0)
这将是我的看法,它使用2个单独的查询来保持数据分离。我使用fetchAll()来简洁,但这可能会有性能问题,幸运的是这可以容纳。我没有进行任何错误检查,如果您需要或有疑问,请询问
<?php
// assume $db is a PDO connection to the database
/* @var $db PDO */
$q = 'SELECT conference_sid, date_created, date_completed, RecordURL, PIN'
.' FROM conference';
// we need these
$conferences = $db->query($q)->fetchAll(PDO::FETCH_CLASS,'stdClass');
// let's group them as CSV, and concatenate the contents with ":"
$q = 'SELECT conference_sid,GROUP_CONCAT(CONCAT_WS(":",call_from,name_recording)) AS parts '
.' FROM participants GROUP BY conference_sid';
$conf_parts = array();
foreach ($db->query($q)->fetchAll(PDO::FETCH_CLASS,'stdClass') as $parts) {
// save the participants as an array, their data is still joined though
$conf_parts[$parts->conference_sid] = explode(',',$parts->parts);
// their contents will be exploded later
}
?>
<table>
<thead><th>Date</th><th>Duration</th><th>Participants</th><th>Recording</th></thead>
<tbody><?php foreach ($conferences as $conference) {
$csid = $conference->conference_sid;
// http://stackoverflow.com/questions/3108591/calculate-number-of-hours-between-2-dates-in-php
// Create two new DateTime-objects...
$date1 = new DateTime($conference->date_completed);
$date2 = new DateTime($conference->date_created);
// The diff-methods returns a new DateInterval-object...
$diff = $date2->diff($date1);
?><tr id="<?php echo $csid; ?>">
<td><?php echo $conference->date_created; ?></td>
<td><?php echo $diff->format('H/i/s'); ?></td>
<td>
<ul><?php foreach ($conf_parts[$csid] as $participant) {
// we have each participant for this conference call
list ($call_from, $name_recording) = explode($participant,':');
// and now we have the required data from each participant
?><li><a href="<?php echo $name_recording ?>"><?php echo $call_from; ?></a></li><?php
} ?></ul>
</td>
<td>
<a href="<?php echo $conference->RecordURL; ?>">Call recording</a>
</td>
</tr><?php
} ?></tbody>
</table>
答案 5 :(得分:0)
首先,我们需要得到我们的结果。
$vPIN = $_SESSION['PIN']; // or however you get your user's pin from session
$vQuery = "SELECT * FROM conference AS a LEFT JOIN participants as B USING (conference_sid) WHERE a.PIN='$vPIN'";
$oResult = $oDB->execute($vQuery);
$aRows = $oResult->fetchAll(PDO::FETCH_ASSOC);
注意前缀:$ v如果对于一个简单的变量,$ o表示一个ressource(我喜欢将其视为一个对象),$ a表示一个数组。这只是为了我的精神健康。
所以现在,我们有一个数组,可能非常大,包含会议桌中的每一行,与参与者中的每一对应行相对应。很好,现在让我们构建一个有一些含义的数组。
foreach($aRows as $aRow) // maybe a bit confusing but the 's' changes everything: all rows vs one row
{if (!isset($aConferences[$aRow['conference_sid']]['infos']))
{$aConferences[$aRow['conference_sid']]['infos']['date_created'] = $aRow['date_created'];
$aConferences[$aRow['conference_sid']]['infos']['date_completed'] = $aRow['date_completed'];
$aConferences[$aRow['conference_sid']]['infos']['record_url'] = $aRow['RecordURL'];
$aConferences[$aRow['conference_sid']]['infos']['pin'] = $aRow['PIN'];}
$aConferences[$aRow['conference_sid']]['participants'][] = $aRow['call_from'];}
所以这里发生的是,对于每一行,如果没有设置相应的conference_sid的信息,它们将是,然后我们为该会议的每个call_from创建一个从0到x的列表。具有虚拟值的该数组的print_r:
[1627]['infos']['date_created'] = 2013-11-26
['date_completed'] = 2013-11-29
['record_url'] = 'http://whatever.com'
['PIN'] = 139856742
['participants'][0] = Bob
[1] = gertrude
[2] = Foo
[8542]['infos']['date_created'] = 2013-12-01
['date_completed'] = 2013-12-02
['record_url'] = 'http://whateverelse.com'
['PIN'] = 584217
['participants'][0] = Family Guy
[1] = aragorn
[2] = obama
[3] = Loki
所以这里有一个很好的数组,我们可以用它来构建一个html表!让我们这样做
$vHTML = '<table>
<thead>
<th>Date</th>
<th>Duration</th>
<th>Participants</th>
<th>Recording</th>
</thead>
<tbody>';
foreach ($aConferences as $conference_sid => $aConference) // notice the s and no s again
{$vHTML.= '<tr id="' . $conference_sid . '">';
$vDateCreated = $aConference['infos']['date_created'];
$vDateCompleted = $aConference['infos']['date_completed'];
$vHTML.= '<td>' . $vDateCreated . '</td>';
$vHTML.= '<td>' . date('Y-m-d',(strtotime($vDateCompleted) - strtotime($vDateCreated))) . '</td>'; // you might have to debug that date diff for yourself.
$vHTML.= '<td><ul>'; // here a foreach for the participants
foreach ($aConference['participants'] as $call_from)
{$vHTML.= '<li>' . $call_from . '</li>';}
$vHTML.= '</ul></td>';
$vHTML.= '<td>' . $aConference['infos']['record_url'] . '</td>';
$vHTML.= '</tr>';}
$vHTML.= '</tbody></table>';
所以这里:为每个会议创建一个包含信息的表格行,然后为每个参与者在列表中添加一个列表项目。如果你想要任何精确度,请发表评论。
哦,不要忘记用$ vHTML做点什么。比如echo $ vHTML:)