Хорошо, вот моя проблема. Я добавляю таблицу в существующую базу данных для хранения заметок по проекту.

«worklog» — это таблица с проектами «worklognotes» — это таблица с примечаниями к проекту

Заметки будут отображаться как цепочка обсуждений. Столбцы worklognotes настроены как этот идентификатор, worklog_id, метка времени, заметки.

"id" - это уникальный идентификатор таблицы. «worklog_id» — это идентификатор проекта, к которому относится заметка, которая хранится в другой таблице. "Временная метка" - это хорошо. "Заметки" с временной меткой - это фактические текущие заметки о проекте. К одному проекту может быть много заметок.

Глядя на запрос базы данных ниже. Я присоединился к двум запросам: «Это мое первое присоединение, поэтому я не уверен, что сделал это правильно». Он читает информацию в обеих таблицах и отображает ее. Но приведенный ниже код отображает каждую запись в «рабочем журнале», которая имеет запись в таблице «worklognotes». Мне нужно, чтобы отображалась одна запись из «рабочего журнала» и много заметок из «рабочего журнала».

Можете помочь или подсказать направление?

$connection = mysql_connect ("localhost", "user", "pass") or die ("I cannot connect to the database.");
$db = mysql_select_db ("database", $connection) or die (mysql_error());

$query = "SELECT * FROM worklog ";  
$query .= "JOIN worklognotes ON worklog_id = worklognotes.worklog_id ";  
$query .= "WHERE worklognotes.worklog_id=worklog.id ORDER BY worklognotes.id DESC";
0
KingMob 12 Янв 2011 в 00:28
Это помогло мне, когда я изучал SQL: codinghorror.com/blog/2007/10/…
 – 
PostMan
12 Янв 2011 в 00:30
Отформатируйте код, сделав отступ в 4 пробела и заключив встроенный код в `. (Кнопка «Попробовать код» ({}) в редакторе.)
 – 
Kissaki
12 Янв 2011 в 00:32
Да и нет. Это получение информации из рабочего журнала и рабочих журналов. Но приведенный ниже код отображает каждую запись в «рабочем журнале», которая имеет запись в таблице «worklognotes».
 – 
KingMob
12 Янв 2011 в 00:33

4 ответа

Ваш запрос на создание JOIN выглядит правильно, но ваше предложение where является избыточным. Попробуй это:

SELECT *
FROM worklog
JOIN worklognotes ON worklog_id = worklognotes.worklog_id
ORDER BY worklognotes.id DESC

Однако для ваших конкретных требований (извлечение одной записи из одной таблицы и нескольких записей из другой) кажется, что нет необходимости в присоединении. Я думаю, что лучше всего запускать два отдельных запроса, иначе вы получите все данные из первой таблицы, повторяющиеся в каждой строке вашего набора результатов.

2
Mark Byers 12 Янв 2011 в 00:37

Скорее всего, вы хотите:

SELECT *
FROM worklog
LEFT JOIN worklognotes ON worklog_id = worklognotes.worklog_id
WHERE worklog_id = $worklog_id
ORDER BY worklognotes.timestamp DESC;

Это выведет только рабочий журнал, идентификатор которого хранится в $worklog_id (скажем, 57), и любые/все связанные заметки рабочего журнала, самые новые отображаются первыми.

Ваш запрос вытягивал ВСЕ рабочие журналы и ВСЕ рабочие журналы, поскольку вы не указали, какой именно рабочий журнал вы хотите, просто у них должен был быть рабочий журнал.

1
Marc B 12 Янв 2011 в 00:31

Вот как работает соединение. Вы получите одну строку для каждой допустимой комбинации. Самое близкое к тому, чего вы хотите, — это объединение всех рабочих заметок.

SELECT workitem.workID, GROUP_CONCAT( worknotes.note ) 
FROM  `workitem` 
JOIN worknotes ON worknotes.workID = workitem.workID
GROUP BY workID

Это даст вам только одну строку для каждого рабочего элемента, и все заметки будут объединены и разделены с помощью ,

В зависимости от ваших имен столбцов вы можете упростить запрос с помощью естественного соединения:

SELECT workID, GROUP_CONCAT( worknotes.note ) 
FROM  `workitem` 
NATURAL JOIN  worknotes
GROUP BY `workID`

Естественное соединение не является стандартным SQL, но это очень удобный инструмент. Если есть ТОЛЬКО ОДИН столбец, общий для двух таблиц, он соединит их так же, как внутреннее соединение с предложением where.

Если вы хотите использовать другой разделитель:

SELECT workID, GROUP_CONCAT( worknotes.note SEPARATOR '; ') 
    FROM  `workitem` 
    NATURAL JOIN  worknotes
    GROUP BY `workID`

Подробности о GROUP_CONCAT:

http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

1
Oliver A. 12 Янв 2011 в 01:25

Глядя на запрос базы данных ниже. Я присоединился к двум запросам: «Это мое первое присоединение, поэтому я не уверен, что сделал это правильно». Он читает информацию в обеих таблицах и отображает ее. Но приведенный ниже код отображает каждую запись в «рабочем журнале», которая имеет запись в таблице «worklognotes». Мне нужно, чтобы отображалась одна запись из «рабочего журнала» и много заметок из «рабочего журнала».

Да, вот как это работает, когда вы присоединяетесь. Вы получите запись рабочего журнала и запись worklognotes в виде одной строки. Это означает, что у вас будет одна и та же запись рабочего журнала несколько раз, если только в ней нет только одной записи рабочего журнала. Вам нужно разобраться с этим на стороне php, если вы хотите отображать в какой-то иерархии.

Поэтому, если вам нужны все рабочие журналы (или больше, чем один) и их заметки, вы должны использовать имеющийся у вас запрос, а затем перебирать результаты для организации, а затем, например, предположить, что $result - это ваш ресурс mysql_result и $worklog_columns и $worklognote_columns содержат массив имен столбцов для каждой таблицы в формате 'column_name' => null, тогда вы можете сделать что-то вроде следующего:

$worklog = array();

while(false !== ($record = mysql_fetch_assoc($result))){
  // get only the data for a worklognote
  $note = array(array_intersect_key($result, $worklognote_columns)); 

  // get the primary key of the worklog
  $id = $record['worklog_id'];


  if(!isset($worklog[$id])){
    // if we havent already processed this worklog form a previous row

    // get the work log data in a separate array
    $log = array_intersect_key($result, $worklog_columns);

    // add a notes key which will hold an array of worklog_notes
    // and assifn the note joined to this row as the first note
    $log['notes'] = array($note);
  }
  else
  {
     // otherwise jsut append the not joined to this row
     // to the existing worklog we processed
     $worklog[$id]['notes'][] = $note;
  }
}

Однако вы должны знать, что если две таблицы, к которым вы присоединяетесь, имеют столбцы с одинаковыми именами, то при использовании MYSQL_ASSOC вы получите значение только из столбца в присоединенной таблице, а не из обоих. ЕСЛИ вам нужен доступ к значению в обеих таблицах, вам нужно либо использовать MYSQL_NUM, либо MYSQL_BOTH, либо использовать псевдоним для каждого столбца в вашем запросе.

0
prodigitalson 12 Янв 2011 в 00:51