2011-08-19 40 views
1
ItemID | File      

1   /storage/somefile1.jpg 
1   /storage/somefile2.jpg 
1   /storage/somefile3.jpg 
1   /storage/somefile5.jpg 

2   /storage/somerandomfile.jpg 
2   /storage/anotherrandomfile.jpg 
2   /storage/yetanotherrandomfile.jpg 
2   /storage/somefile.jpg 

我想为每个文件创建一个新的列,而不是每个文件1行。如:MySQL将具有相同ID的多行值复制到新列中?

ItemID | File      | File2      | File3 etc... 

1   /storage/somefile1.jpg  | /storage/somefile2.jpg  | /storage/.. 


2   /storage/somerandomfile.jpg | /storage/anotherrandomfile.jpg | /storage/.. 

有没有什么办法与查询自动完成这个?

+0

我不这么认为。 AFAIK,你将不得不使用一些脚本来创建查询。你使用什么编程语言? – shesek

+0

我正在使用PHP 5.2.x –

+0

您的数据库设计看起来是最佳的。你确定要改变它吗?你试图解决什么确切的问题? –

回答

0

看到你的评论和你只是试图让一个CSV了它之后,你可以做这样的事情:

<?php 
$query = $db->query('SELECT ItemID, GROUP_CONCAT(File SEPARATOR \'|$|\') AS Files FROM Table GROUP BY ItemID'); 
// Use a string that cant appear as part of the filename as the separator 
$fh = fopen('items.csv', 'w'); 
foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { 
    $files = explode('|$|', $row['Files']); 
    fputcsv($fh, array_merge(array($row['ItemID']), $files)); 
} 
fclose($fh); 
0

不,你不能这样做(改变mysql方案)。

+0

如果我手动创建了新的列和列File1到File5,那么现有的所有就绪代码都可以遍历具有相同ID的每一行,然后将原始列的内容复制到每个新的空列中? –

+0

当然。但是编写用于填充这些行的脚本会更好。 –

0

继我对这个问题的评论,你可以创建一个新表与你需要的模式,并运行类似的东西(假设PDO):

<?php 
$db->beginTransaction(); 
$query = $db->query('SELECT ItemID, GROUP_CONCAT(File SEPARATOR \'|$|\') AS Files FROM Table GROUP BY ItemID'); 
// Use a string that cant appear as part of the filename as the separator 
$sth = $db->prepare('INSERT INTO NewTable (ItemID, File1, File2, File3) VALUES (:ItemID, :File1, :File2, :File3)'); 
foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { 
    $files = explode('|$|', $row['Files']); 
    $sth->execute(array(
     'ItemID' => $row['ItemID'], 
     'File1' => isset($files[0]) ? $files[0] : NULL, 
     'File2' => isset($files[1]) ? $files[1] : NULL, 
     'File3' => isset($files[2]) ? $files[2] : NULL, 
    )); 
} 
$db->commit(); 

不过,我觉得你目前的架构设计是更好。你为什么要改变它?

+0

仅用于为CSV导出准备数据,以便将其导入到不同的CMS中,将所有文件按1 ID进行分组只是使该过程的一部分更容易,即使最终它最终会以类似的模式结束。也许有一种更简单的方法来制作一个查询,使其“看起来”,而不是将文件移动到自己的列中。 –

0

如果要生成SQL您的CSV权利,你可以使用下面的查询为出发点:

SELECT CONCAT_WS(',', ItemID, GROUP_CONCAT(File ORDER BY File SEPARATOR ',')) AS FullCSVRow 
FROM ItemToFile 
GROUP BY ItemID 

...返回:

FullCSVRow 
1,/storage/somefile1.jpg,/storage/somefile2.jpg,/storage/somefile3.jpg,/storage/somefile5.jpg 
2,/storage/somerandomfile.jpg,/storage/somerandomfile.jpg,/storage/somerandomfile.jpg,/storage/somerandomfile.jpg 
3,/storage/file-1-of-2.jpg,/storage/file-2-of-2.jpg 

如果您正在使用PHP,您可以完全控制您执行哪些查询以及如何构建它们。您不需要更改数据库设计。

+0

这是一个明智的做法,但是如果任何文件名中包含','可能会产生问题,因为它不会被正确转义以用于CSV格式 – shesek

+0

@shesek:...并且如果有项目没有4个文件,就像我的例子。这就是我的意思是“出发点”:)无论如何,我会用PHP来做到这一点。 –

0
SELECT 
    ItemID, 

    (SELECT t2.File FROM (SELECT @row := @row + 1 AS r, File FROM my_table AS t3 
    JOIN (SELECT @row := 0) AS init 
    WHERE t1.ItemID = t3.ItemID ORDER BY t3.File) AS t2 WHERE t2.r = 1), 

    (SELECT t2.File FROM (SELECT @row := @row + 1 AS r, File FROM my_table AS t3 
    JOIN (SELECT @row := 0) AS init 
    WHERE t1.ItemID = t3.ItemID ORDER BY t3.File) AS t2 WHERE t2.r = 2), 

    (SELECT t2.File FROM (SELECT @row := @row + 1 AS r, File FROM my_table AS t3 
    JOIN (SELECT @row := 0) AS init 
    WHERE t1.ItemID = t3.ItemID ORDER BY t3.File) AS t2 WHERE t2.r = 3), 

    (SELECT t2.File FROM (SELECT @row := @row + 1 AS r, File FROM my_table AS t3 
    JOIN (SELECT @row := 0) AS init 
    WHERE t1.ItemID = t3.ItemID ORDER BY t3.File) AS t2 WHERE t2.r = 4) 

    FROM my_table AS t1 
相关问题