无法理解如何正确加入mySQL表

时间:2011-01-11 21:28:14

标签: php mysql join

好的,这是我的问题。 我正在向现有数据库添加一个表来存储项目注释。

“worklog”是包含项目的表 “worklognotes”是包含项目说明的表

笔记将像讨论主题一样显示。 worklognotes列的设置类似于id,worklog_id,timestamp,notes。

“id”是表唯一ID。 “worklog_id”是注释所包含的项目的id,存储在另一个表中。 “timestamp”很好地是一个时间戳 “笔记”是关于该项目的实际持续笔记。单个项目可能有很多笔记。

查看下面的数据库查询。我加入了两个问题“这是我的第一次加入所以我不确定我做得对。” 它正在读取两个表中的信息并显示它。 但是下面的代码显示“worklog”中的每个条目,该条目在“worklognotes”表中有记录。 我需要它来显示“worklog”中的一个条目和“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";

4 个答案:

答案 0 :(得分:2)

您创建JOIN的查询看起来是正确的,但您的where子句是多余的。试试这个:

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

但是,对于您的特定要求(从一个表中获取一个记录而从另一个表中获取多个记录),似乎不需要加入。我认为最好运行两个单独的查询,否则您将在结果集的每一行中重复第一个表中的所有数据。

答案 1 :(得分:1)

你最有可能想要:

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)中的id的工作日志,以及最新显示的任何/所有相关工作日记录。

您的查询是提取所有工作日志和所有工作日志,因为您没有准确指定所需的工作日志,只是他们必须有工作标识。

答案 2 :(得分:1)

这就是联接的工作方式。每个有效组合将获得一行。最接近你想要的是聚合所有工作注意事项。

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

答案 3 :(得分:0)

  

查看下面的数据库查询。一世   加入了两个问题“这是我的   首先加入,所以我不确定我做了什么   它是正确的。“它正在阅读   表格和表格中的信息   显示它。但是下面的代码是   显示“工作日志”中的每个条目   有记录的   “worklognotes”表。我需要它   显示“工作日志”中的一个条目   来自“worklognotes”的许多笔记

是的,这就是你加入时的工作方式。您将获得工作日志条目和工作日志条目作为单行。这意味着您将多次拥有相同的工作日志条目,除非它只有一个工作标识。如果你想在某种层次结构中显示,你需要在php端对此进行排序。

因此,如果您想要所有工作日志(或者真的超过jsut)及其注释,您将使用您拥有的查询,然后迭代结果以进行适当组织,例如假设$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或别名。