简体   繁体   中英

MySQL joining tables one-to-many relationship

I am trying to achieve something in MySQL but even with all the answers here or on other sites, I still cannot accomplish the goal.

I have two tables, in one-to-many relationship.

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

TABLE Files_Meta
COLUMNS id, parent_id, key, value

Obviously each file has multiple meta data represented as many rows in the Files_Meta table. For example File1 has meta Author, Place, Time, Tags, Camera -- if it's a photo.

I'm trying to select all rows from Files table including meta data.

Standard result

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
)

What I want

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

Is it possible to achieve this in MySQL? Doesn't have to look like this, without that array.

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

Thanks in advance for replies or tips.

Doing this in a single query could be as follows:

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

Per the comments, you will need PHP to create the structure you desire as MySQL only returns results in a flat fashion.

I strongly advise writing your code to do this in a single query or with 2 queries - one for all Files and another for all Files_Meta . Then stitch the data together with PHP. Otherwise, you may create an N+1 Problem .

As an aside, I recommend changing parent_id to file_id . parent_id typical denotes of a self-referential key. Whereas file_id would denote a foreign key to the File table.

As you also tagged PHP - I would recommend you to use an PHP ORM Framework like Doctrine or Propel which would give you a structure like that (which is very abstract):

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

}

The only thing you have to do is define your structure (maybe exported from your database) and thats it.

I hope this is not too far away from what you searched.

Sounds like you are looking for a join. This would be great if there was only one meta per file. More than one meta per file would result in numerous resulting rows with only the meta data being different. However, I assume since you are displaying photo data that this is not true and would only get one meta per file so I would suggest this 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

This will give you a flat representation consisting of the data you were fetching in two separate queries and then combining via PHP. Relying on your database is always better than having to manually stitch stuff together when possible and as long as the parent_id and the id in files are indexed the query should be lightning fast.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM