【发布时间】:2011-11-27 18:05:22
【问题描述】:
我想合并两个 MySQL 表,但在其中一个表中使用一些数据作为合并表中的新表头。我有两张桌子,像这样:
我们每天吃的水果的日志。
id 日期 水果 5 2011-11-27 香蕉 4 2011-11-26 苹果 3 2011-11-25 橙色 2 2011-11-24 香蕉 1 2011-11-23 梨一张桌子,上面写着我们对我们吃过的水果的看法。
id user fruit rating 7安德鲁香蕉百胜 6 安德鲁苹果 eww 5 丽莎苹果百胜 4安德鲁橙百胜 3丽莎橙百胜 2 安德鲁梨 eww 1 丽莎梨 eww我正在寻找的是一个 SQL 查询,其结果如下:
date fruit andrew lisa 2011-11-27 香蕉百胜 NULL 2011-11-26 苹果 eww 百胜 2011-11-25 橙 百胜 百胜 2011-11-24 香蕉百胜 NULL 2011-11-23 梨 eww eww我想我不是第一个想要这样的东西的人;但是当您不知道如何描述它时,除了显示表格和所需的结果之外,寻找答案并不容易。
为了我自己的实验,我现在实际上已经创建了上面使用的示例表。 (我真正需要的在概念上是相似的,但我实际上不认识任何名叫安德鲁的人,我也不记录我们吃的水果。无论如何,真正的桌子更大更复杂 - 这些可以用来描述这个概念.
--
-- Table structure `fruit_log`
--
CREATE TABLE IF NOT EXISTS `fruit_log` (
`id` int(11) NOT NULL auto_increment,
`date` date NOT NULL,
`fruit` varchar(6) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
--
-- Dumping of data in table `fruit_log`
--
INSERT INTO `fruit_log` (`id`, `date`, `fruit`) VALUES
(1, '2011-11-23', 'pear'),
(2, '2011-11-24', 'banana'),
(3, '2011-11-25', 'orange'),
(4, '2011-11-26', 'apple'),
(5, '2011-11-27', 'banana');
--
-- Table structure `fruit_log`
--
CREATE TABLE IF NOT EXISTS `fruit_ratings` (
`id` int(11) NOT NULL auto_increment,
`user` varchar(6) NOT NULL,
`fruit` varchar(6) NOT NULL,
`rating` enum('yum','eww') default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
--
-- Dumping of data in table `fruit_ratings`
--
INSERT INTO `fruit_ratings` (`id`, `user`, `fruit`, `rating`) VALUES
(1, 'lisa', 'pear', 'eww'),
(2, 'andrew', 'pear', 'eww'),
(3, 'lisa', 'orange', 'yum'),
(4, 'andrew', 'orange', 'yum'),
(5, 'lisa', 'apple', 'yum'),
(6, 'andrew', 'apple', 'eww'),
(7, 'andrew', 'banana', 'yum');
在试图找到这个问题的答案时,我学到了很多东西。首先,“数据透视表”作为一个概念,由 @w0051977 介绍给我。但是 w0051977 的链接特定于 Microsoft SQL Server - 我运行 MySQL。无论如何,我被介绍了这个概念,并进一步观察。我从 Wikipedia 中学到了一些东西,并从这个编年史中学到了很多东西:http://dev.mysql.com/tech-resources/articles/wizard/print_version.html
但是;我一直找不到任何与我的目标相近的东西。困难的部分似乎是使用动态数量的单元格数据(来自“用户”列的数据:在我的示例中为“andrew”和“lisa”,但也可能包括“bob”甚至“alice”等)和将它们“翻转”为列标题。
向导在上面链接的编年史中执行此操作,但不是在单个查询中:他使用巧妙的 SQL 技巧生成另一个 SQL 查询的一部分,该查询可以粘贴到执行他想要执行的操作的查询中.当然,您不必实际复制和粘贴它——Wizard 使用 Perl 将其自动化,而我会使用 PHP(这是基于 PHP 的项目的一部分)。但是如果我无论如何都必须使用PHP来生成查询,我还不如用更简单的方式来做。
@adam-wenger 建议我使用 LEFT JOIN,但指出它只能用于有限数量的用户。这是他的查询,适用于我在上面发布他的答案后在编辑中介绍的表名。
SELECT fruit_log.date, fruit_log.fruit, a.rating AS 'andrew', l.rating AS 'lisa'
FROM fruit_log
LEFT JOIN fruit_ratings AS a
ON fruit_log.fruit = a.fruit
AND a.user = 'andrew'
LEFT JOIN fruit_ratings AS l
ON fruit_log.fruit = l.fruit
AND l.user = 'lisa'
ORDER BY date DESC
使用 PHP,我可以根据需要生成任意数量的 LEFT JOIN,从而解决我的问题。我也可以使用子查询,如下所示:
SELECT fruit_log.date, fruit_log.fruit, (
SELECT fruit_ratings.rating
FROM fruit_ratings
WHERE fruit_ratings.user = 'andrew'
AND fruit_ratings.fruit = fruit_log.fruit
) AS 'andrew', (
SELECT fruit_ratings.rating
FROM fruit_ratings
WHERE fruit_ratings.user = 'lisa'
AND fruit_ratings.fruit = fruit_log.fruit
) AS 'lisa'
FROM fruit_log
ORDER BY date DESC
我想其中一个比另一个更有效,但我不知道哪一个(如果我有时间和兴趣,我会做一个基准测试,除非有人在此之前提供洞察力)。
如果有人对我的问题有一个单一的查询解决方案,将不胜感激。直到那时;我将不得不坚持使用 PHP ducttape(这个问题仍然没有答案)。
【问题讨论】:
标签: mysql sql join pivot-table