该问题被标记为问题的“重复” mySQL - Create a New Table Using Data and Columns from Three Tables
我认为问题不同,因为有三个表在行动,在我的问题中是两个。那里的问题是如何创建一个新表,这里的问题是创建一个输出。 但是感谢你的指点,也许它比我期待的更接近我的问题。
我尝试使用“Duplicate”-Question中的解决方案,但是Ansers和问题并不是很相似。
根据“重复” - 问题,我试过
SELECT i.ID as ItemID, i.Name as ItemName,
p1.Value AS Color, p2.Value AS Speed, p3.Value AS Price
FROM items as i
JOIN itemproperties AS p1 ON (i.ID=p1.ItemID)
JOIN itemproperties AS p2 ON (i.ID=p2.ItemID)
JOIN itemproperties AS p3 ON (i.ID=p3.ItemID)
WHERE (p1.Name = 'Color') and (p2.Name = 'Speed') and (p3.Name = 'Price')
但结果只有一行
ItemID, ItemName, Color, Speed, Price
1, Car, blue, 200, 50000
而不是预期的四行,在没有找到属性名称的地方包含值“(NULL)”。
所以恕我直言“复制” - 问题是不同的,并没有回答我的问题!
原始问题:
我的个人SQL技能有限。环顾四天后,我没有找到任何有效的解决方案来解决我的数据库查询问题。我在这个问题的最后附上了完整的示例数据库SQL文本。 我的示例数据库(使用MariaDB制作)包含两个表:
对于每件商品,仅定义 item.ID 和 item.Name 。 (在现实生活中的例子中,名称将被定义为唯一的。)
对于每个项目,都可以使用动态用户定义的属性集。这些属性定义为名称 - 值对。 例如,对于名为“ Banana ”的项目,可能存在值为“黄色”的属性“颜色”。
只有一个项目具有一个“颜色”属性才有效,因此不能为一个项目分配两种不同的颜色。
(在我的实际问题中,属性名称只包含两个字符,因此不需要额外的属性名称表,以及随后为了便于显示示例中未使用的问题)。
items表的示例数据:
ID, Name
1, Car
2, House
3, Homer
4, Earth
定义了上述项目的总共九个属性。条目“(NULL)”表示未为给定项
定义此属性ItemID, ItemName, Color, Speed, Price
1, Car, blue, 200, 50000
2, House, red, (NULL), 250000
3, Homer, yellow, 5, (NULL)
4, Earth, blue, 108000, (NULL)
不幸的是我的选择陈述
SELECT items.ID as ItemID, items.Name as ItemName,
CASE WHEN (itemproperties.Name = 'Color')
THEN itemproperties.Value
#ELSE NULL
END as Color,
CASE WHEN (itemproperties.Name = 'Speed')
THEN itemproperties.Value
#ELSE NULL
END as Speed,
CASE WHEN (itemproperties.Name = 'Price')
THEN itemproperties.Value
#ELSE NULL
END as Price
FROM items left join itemproperties
ON (items.ID=itemproperties.ItemID)
返回这样的数据
ItemID, ItemName, Color, Speed, Price
1, Car, blue, (NULL), (NULL)
1, Car, (NULL), 200, (NULL)
1, Car, (NULL), (NULL), 50000
2, House, red, (NULL), (NULL)
2, House, (NULL), (NULL), 250000
3, Homer, yellow, (NULL), (NULL)
3, Homer, (NULL), 5, (NULL)
4, Earth, blue, (NULL), (NULL)
4, Earth, (NULL), 108000, (NULL)
问题:如何编写select语句以整理形式获取数据,每个项目一行? 非常感谢你!
问候Ekkehard
数据库定义:
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server Version: 10.1.13-MariaDB - mariadb.org binary distribution
-- Server Betriebssystem: Win32
-- HeidiSQL Version: 9.4.0.5125
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Exportiere Datenbank Struktur für DynamicColTest
CREATE DATABASE IF NOT EXISTS `dynamiccoltest` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `DynamicColTest`;
-- Exportiere Struktur von Tabelle DynamicColTest.itemproperties
CREATE TABLE IF NOT EXISTS `itemproperties` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Unique ID of the property',
`ItemID` int(10) unsigned DEFAULT '0' COMMENT 'ID of the Item this property belongs to',
`Name` varchar(20) DEFAULT '0' COMMENT 'Name of the property',
`Value` varchar(20) DEFAULT '0' COMMENT 'Value of the property',
UNIQUE KEY `Schlüssel 3` (`Name`,`ItemID`),
KEY `Schlüssel 1` (`ID`),
KEY `FK_itemproperties_items` (`ItemID`),
CONSTRAINT `FK_itemproperties_items` FOREIGN KEY (`ItemID`) REFERENCES `items` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 COMMENT='The properties of the items';
-- Exportiere Daten aus Tabelle DynamicColTest.itemproperties: ~9 rows (ungefähr)
DELETE FROM `itemproperties`;
/*!40000 ALTER TABLE `itemproperties` DISABLE KEYS */;
INSERT INTO `itemproperties` (`ID`, `ItemID`, `Name`, `Value`) VALUES
(1, 1, 'Color', 'blue'),
(1, 4, 'Color', 'blue'),
(1, 2, 'Color', 'red'),
(2, 3, 'Color', 'yellow'),
(3, 1, 'Speed', '200'),
(3, 4, 'Speed', '108000'),
(4, 3, 'Speed', '5'),
(5, 1, 'Price', '50000'),
(5, 2, 'Price', '250000');
/*!40000 ALTER TABLE `itemproperties` ENABLE KEYS */;
-- Exportiere Struktur von Tabelle DynamicColTest.items
CREATE TABLE IF NOT EXISTS `items` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Unique Item ID',
`Name` varchar(25) DEFAULT '0' COMMENT 'Name of the Item',
KEY `Schlüssel 1` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 COMMENT='Contains all Items, with a minimum of definitions';
-- Exportiere Daten aus Tabelle DynamicColTest.items: ~4 rows (ungefähr)
DELETE FROM `items`;
/*!40000 ALTER TABLE `items` DISABLE KEYS */;
INSERT INTO `items` (`ID`, `Name`) VALUES
(1, 'Car'),
(2, 'House'),
(3, 'Homer'),
(4, 'Earth');
/*!40000 ALTER TABLE `items` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
答案 0 :(得分:0)
3 JOINs vs 2没有显着差异。
想要缺少属性的NULL是的区别。 (因此重新开放。)
您需要LEFT JOIN
而不是JOIN
和将WHERE
子句移到ON
子句中。 (这是少数情况之一,在ON
与WHERE
中是否存在条件真的很重要。)
SELECT i.ID as ItemID, i.Name as ItemName,
p1.Value AS Color, p2.Value AS Speed, p3.Value AS Price
FROM items as i
LEFT JOIN itemproperties AS p1 ON i.ID=p1.ItemID AND p1.Name = 'Color'
LEFT JOIN itemproperties AS p2 ON i.ID=p2.ItemID AND p2.Name = 'Speed'
LEFT JOIN itemproperties AS p3 ON i.ID=p3.ItemID AND p3.Name = 'Price'
WHERE p1.Value IS NOT NULL
OR p2.Value IS NOT NULL
OR p3.Value IS NOT NULL;
性能不会很好,但那是实体 - 属性 - 值模式的一般问题。
有一点可以帮助我在itemproperties
:
PRIMARY KEY(ItemID, Name) -- in this order
并使用ENGINE=InnoDB
。
如果您需要进一步讨论,请提供SHOW CREATE TABLE
和EXPLAIN SELECT
。
(其中一项尝试可以通过MAX
和GROUP BY
修复。)
答案 1 :(得分:0)
您可以通过这种方式在没有每个属性的连接的情况下执行此操作:
SELECT i.ID, i.Name,
MAX(IF(p.Name='Color', p.value, NULL)) AS Color,
MAX(IF(p.Name='Speed', p.value, NULL)) AS Speed,
MAX(IF(p.Name='Price', p.value, NULL)) AS Price
FROM items i
LEFT JOIN itemproperties p
ON (i.ID=p.ItemID)
GROUP BY i.ID
输出:
+----+-------+--------+--------+--------+
| ID | Name | Color | Speed | Price |
+----+-------+--------+--------+--------+
| 1 | Car | blue | 200 | 50000 |
| 2 | House | red | NULL | 250000 |
| 3 | Homer | yellow | 5 | NULL |
| 4 | Earth | blue | 108000 | NULL |
+----+-------+--------+--------+--------+
但使用EAV数据总是很尴尬和风险。如果可以,请避免使用它。
PS:您还应该为items表声明主键约束。
alter table items add primary key (ID);