2013-11-25 22 views
2

兩個MySQL表結果我有以下兩種表結構在MySQL中,其中一個電話會議記錄的細節和那些加入了它的參與者:如何輸出結合使用PDO

表:會議:

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> 

我只希望這個表來顯示相關結果有相同的PIN作爲用戶的會話會議::得到(「密碼」)

+4

http://en.wikipedia.org/wiki/Join_%28SQL%29祝你好運 –

+0

謝謝,如果我想保持獨立的表將加入仍然是最合適的方法? – alias51

+0

表格將保持獨立。使用連接只允許您在一個查詢中從兩個表中獲取數據 – AdRock

回答

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和MySQL文檔關於TIMEDIFF結合參與者。

現在,應用程序邏輯將

<?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 ]) 

返回一個字符串數組,其中每一個是通過拆分它在由字符串分隔符形成的邊界處形成串 的子串。

2

我不會做PHP的一部分,因爲我不是在PHP是知識淵博,但這裏是SQL:

SELECT * 
FROM `conference`, `participants` 
WHERE `conference`.PIN = $PIN AND 
     `participants`.conference_sid = `conference`.conference_sid 

這將返回的信息行從conferenceparticipants的那些conferences,加入一行。

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變化時,外部循環應該前進。內部循環將顯示該會議參與者列表的每個元素。

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構造。

希望這會有所幫助!

+0

謝謝,您會推薦什麼樣的錯誤處理/當您說逃脫數據時,您的意思是什麼? – alias51

+0

這裏的錯誤處理比根本沒有的情況更糟糕。 –

+0

@YourCommonSense你是對的...修正了一些事情 – fthiella

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> 
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); 

音符前綴:如果對於一個簡單的變量$ o表示一個的ressource(我喜歡把作爲對象)$ V,$ 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的相關信息尚未確定,他們會,然後我們從0創建一個列表,每個call_from該會議的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做點什麼。像回聲$ vHTML :)