复杂的SELECT查询

时间:2009-11-09 14:06:30

标签: mysql

我有一个表,用于定义另一个表可以拥有的内容,例如:

CREATE TABLE `objects` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50) NOT NULL
);

INSERT INTO `objects` (`name`) VALUES ('Test');
INSERT INTO `objects` (`name`) VALUES ('Test 2');

CREATE TABLE `properties` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50) NOT NULL
);

INSERT INTO `properties` (`name`) VALUES ('colour');
INSERT INTO `properties` (`name`) VALUES ('size');

CREATE TABLE `objects_properties` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `object_id` INT UNSIGNED NOT NULL,
  `property_id` INT UNSIGNED NOT NULL,
  `value` VARCHAR(50) NOT NULL,
  FOREIGN KEY (`object_id`)
    REFERENCES `objects` (`id`),
  FOREIGN KEY (`property_id`)
    REFERENCES `properties` (`id`)
);

INSERT INTO `objects_properties` (`object_id`, `property_id`, `value`) VALUES 1, 1, 'red');
INSERT INTO `objects_properties` (`object_id`, `property_id`, `value`) VALUES 1, 2, 'small');
INSERT INTO `objects_properties` (`object_id`, `property_id`, `value`) VALUES 2, 1, 'blue');
INSERT INTO `objects_properties` (`object_id`, `property_id`, `value`) VALUES 2, 2, 'large');

希望这是有道理的。基本上不是在对象表中有颜色,大小等列,我有两个其他表,一个定义任何对象可以拥有的属性,另一个将对象链接到部分或全部属性。

我的问题是,是否有某种方法来检索这样的信息:

+--------+------------+------------+
| object | colour     | size       |
+--------+------------+------------+
| Test   | red        | small      |
| Test 2 | blue       | large      |
+--------+------------+------------+

因此,您可以看到列标题实际上是行值。我不确定与做一些单独的查询并将所有内容放在PHP中相比,它是否可能或成本是多少。

4 个答案:

答案 0 :(得分:4)

SELECT o.name, c.colour, s.size
FROM objects o
LEFT JOIN (SELECT op.object_id, op.value colour
        FROM objects_properties op
        join properties p on op.property_id = p.id and p.name = 'colour') c
ON o.id = c.object_id
LEFT JOIN (SELECT op.object_id, op.value size
        FROM objects_properties op
        join properties p on op.property_id = p.id and p.name = 'size') s
ON o.id = s.object_id

答案 1 :(得分:1)

这里的关键字是“数据透视表”“交叉表”(但是“数据透视表”也在那个方向)而不是,MySQL不能直接执行此操作。您可以创建一个将选择此项的查询,但您必须在查询中自己显式定义列。无法从另一个表中获取列。其他RDBMS可能具备此功能。

答案 2 :(得分:0)

pivot (或类似的东西)可能很有用。在MS SQL Server中,您可以使用它但是,旋转表的值必须是常量,或者您可以使用存储过程来计算它。

此处you can find more info

度过美好的一天!

答案 3 :(得分:0)

SELECT  o.*,
        (
        SELECT  *
        FROM    object_properties op
        WHERE   op.object_id = o.object_id
                AND op.property_id = $prop_color_id
        ) AS color,
        (
        SELECT  *
        FROM    object_properties op
        WHERE   op.object_id = o.object_id
                AND op.property_id = $prop_size_id
        ) AS size
FROM    objects o

$prop_color_id$prop_size_id属性color代替sizeid

要使此查询有效,请在(object_id, property_id)PRIMARY KEY object_properties并删除代理密钥。