MySQL加入表一对多的关系

时间:2012-06-20 15:23:14

标签: php mysql sql

我正在尝试在MySQL中实现某些功能,但即使在这里或在其他网站上获得所有答案,我仍然无法实现目标。

我有两张桌子,一对多关系。

TABLE Files
COLUMNS id, title, description, uploaded, size, extension, etc.

TABLE Files_Meta
COLUMNS id, parent_id, key, value

显然,每个文件都有多个元数据,表示 Files_Meta 表中的多行。例如, File1 包含元作者,地点,时间,标签,相机 - 如果是照片。

我正在尝试从文件表中选择所有行,包括元数据。

标准结果

stdClass Object
(
[id] => 10
[title] => Hello world
[size] => 745198
[extension] => jpg
[user_id] => 0
[category_id] => 0
[date_uploaded] => 2012-06-08 13:37:55
[description] => 
[downloaded] => 0
[viewed] => 8
)

stdClass Object
(
[id] => 90
[parent_id] => 10
[key] => place
[value] => New York
)

我想要什么

stdClass Object
(
[id] => 10
[title] => Hello world
[size] => 745198
[extension] => jpg
[user_id] => 0
[category_id] => 0
[date_uploaded] => 2012-06-08 13:37:55
[description] => 
[downloaded] => 0
[viewed] => 8
[meta] => Array (
    place => New York
    author => John Doe
    time => March 2001
    camera => Canon EOS
    etc.
    )
)

有可能在MySQL中实现这一点吗?没有那个数组,不一定要这样。

stdClass Object
(
[id] => 10
.
.
[place] => New York
[author] => John Doe
[time] => March 2001
[camera] => Canon EOS
)

提前感谢您的回复或提示。

3 个答案:

答案 0 :(得分:1)

在单个查询中执行此操作可能如下所示:

SELECT * FROM Files INNER JOIN Files_Meta ON Files.id = Files_Meta.parent_id

根据评论,您将需要PHP来创建您想要的结构,因为MySQL仅以 flat 方式返回结果。

我强烈建议您编写代码,以便在单个查询或2个查询中执行此操作 - 一个用于所有Files,另一个用于所有Files_Meta。然后用PHP将缝合数据。否则,您可以创建N+1 Problem

另外,我建议将parent_id更改为file_idparent_id典型表示自引用密钥。而file_id表示File表的外键。

答案 1 :(得分:0)

正如您还标记了PHP一样 - 我建议您使用像Doctrine或Propel这样的PHP ORM框架,它会为您提供类似的结构(非常抽象):

class File {

/* members */

var id // int
var title // string
var description // string
var uploaded // boolean
var size // int
var extension // string
var metadata // array (Collection of FileMeta)

/* getters setters for each member */
...

}

class FileMeta {

var id // int
var fileId // the id to the File object
var file // the fileobject itself
var key // string
var value // string

}

您唯一需要做的就是定义您的结构(可能从您的数据库中导出)就是这样。

我希望这与你搜索的内容相差不远。

答案 2 :(得分:0)

听起来你正在寻找加入。如果每个文件只有一个元数据,这将是很好的。每个文件不止一个元数据会产生大量结果行,只有元数据不同。但是,我假设你正在显示照片数据,这不是真的,每个文件只能获得一个元数据,所以我会建议这个SQL:

SELECT 
    Files.*,
    Files_Meta.place, Files_Meta.author, Files_Meta.time, Files_Meta.camera, ..etc 
FROM 
    Files
JOIN Files_Meta ON Files_Meta.parent_id = Files.id

这将为您提供一个平面表示,包含您在两个单独的查询中获取的数据,然后通过PHP进行组合。依赖于您的数据库总是比在必要时手动将东西拼接在一起更好,只要文件中的parent_id和id被索引,查询就应该是快速的。