2012-02-13 5 views
0

Код

В настоящее время мой код выглядит так.Выбор нескольких значений из двух таблиц сразу

  $stmt = $this->db->prepare("SELECT m.id, m.from_id, m.to_id, m.subject, m.date, m.deleted, m.read, u.fname, u.mname, u.lname FROM msghistory AS m,users AS u WHERE m.from_id=u.id AND m.to_id=u.id AND GROUP BY m.id DESC"); 
      $stmt->execute(); 
      $stmt->store_result(); 
      if ($stmt->affected_rows > 0) { 
       $msg = array(); 
       $stmt->bind_result($msg['id'], $msg['from_name'], $msg['to_name'], $msg['subject'], $msg['message'], $msg['date'], $msg['deleted'], $msg['read']); 

       while ($stmt->fetch()) { 
        <echoing results one by one>     } 
      } 

То, что я хочу сделать

Я хочу, чтобы получить u.fname+u.mname+u.lname (Где msghistory.from_id=users.id), как $msg['from_name'], снова u.fname+u.mname+u.lname (НО на этот раз, когда msghistory.to_id=users.id) в $ сообщ [ 'TO_NAME'].

Пример

message | from_id | to-id 
hi  | 1  | 5 

Как вы видите, это означает, что пользователь 1 отправить пользователю сообщение 5 привет.

Допустим, пользователи таблицы имя_файла, LNAME для идентификатора пользователя = 1 - John Doe и 5 - Джордж Смит Я хочу показать это в качестве выходного результата

message | from_id | to-id 
hi  | John Doe| George Smith 

Вопрос

Я знаю, что это возможно, по крайней мере, с тремя запросами. Но пытаясь найти оптимальный путь. Итак, возможно ли это с одним и единственным запросом?

Update

На основании 2 полезных ответов со стороны пользователей я изменил запрос в это

  $stmt = $this->db->prepare("SELECT 
       message.id, message.from_id, message.to_id, message.subject, 
       message.date, message.deleted, message.read, 
       CONCAT_WS(' ',sender.fname, sender.mname, sender.lname) AS sender_name, 
       CONCAT_WS(' ',recipient.fname, recipient.mname, recipient.lname) AS recipient_name, 
       FROM msghistory AS message 
       LEFT JOIN users AS sender ON sender.id=message.from_id, 
       LEFT JOIN users AS recipient ON recipient.id=message.to_id 
       GROUP BY message.id DESC"); 

ответ

1

Используя явное присоединяется и четкие, читаемые псевдонимы делают его как более надежным, так и более легким для чтения. Попробуйте следующее:

SELECT message.*, recipient.*, sender.* 
FROM msghistory AS message 
INNER JOIN users AS recipient ON recipient.id=m.to_id 
INNER JOIN users AS sender ON sender.id=m.from_id 

Вы можете заменить выберите * S только с полями, которые вы хотите для повышения эффективности

+0

проверка обновленный вопрос. Это правильно? –

+0

Он выглядит хорошо. Вам нужно только левое соединение (а не внутреннее соединение), если отправитель и получатель являются необязательными. Если в сообщении всегда есть отправитель и получатель, используйте внутренние соединения, поскольку они более эффективны. Я не знал, что вы можете указать направление asc или desc с предложениями group by. Хорошее знание! – user1207727

1
SELECT m.id, m.from_id, m.to_id, m.subject, m.date, 
m.deleted, m.read, u1.fname, u1.mname, u1.lname, 
u2.fname, u2.mname, u2.lname,  
FROM msghistory AS m,users AS u1, users As u2  
WHERE m.from_id=u1.id AND m.to_id=u2.id 
GROUP BY m.id DESC 

Я не уверен, что вам нужно "группу по"

+0

группы по для, опущенной сортировки. btw я могу выбрать u1.fname, u1.mname, u1.lname как 1 переменную name1 (другими словами, развязать их с пространством внутри запроса в 1 переменную name1)? –

+0

CONCAT (u1.fname, "", u1.lname) AS 'name' – alfasin

+0

Я думаю, что concat не будет работать, если некоторые из этих значений равны нулю. поэтому concat_ws хорош для этой цели, не так ли? –

Смежные вопросы