CREATE TABLE Attributes ( id VARCHAR(40), type VARCHAR(16), data VARCHAR(2048), PRIMARY KEY(id,type) );
这是我尝试运行的查询的一般格式。一般的想法是'对象'具有唯一的ID,然后有一个键/值对,如javascript对象。
SELECT a1.id, a1.data, a2.data, a3.data, a4.data, a6.data FROM Attributes a1, Attributes a2, Attributes a3, Attributes a4, Attributes a5 LEFT JOIN Attributes a6 ON (a6.id=a5.id AND a6.type = 'Foreign Id') WHERE a1.id=a2.id AND a1.id=a3.id AND a1.id=a4.id AND a1.id=a5.id AND a1.type = 'First Name' AND a2.type = 'Middle Name' AND a3.type = 'Last Name' AND a4.type = 'Timestamp' AND a5.type = 'Count' AND a5.data = 'MY_ID'
在此查询中,'Foreign Id'
是可选属性。问题是我得到了
SELECT将检查超过MAX_JOIN_SIZE行;检查你的 WHERE并使用SET SQL_BIG_SELECTS = 1或SET MAX_JOIN_SIZE =#if 选择没问题。
我意识到我可以这样说,但警告让我担心这个查询非常低效。有没有更好的方法来制定查询?
答案 0 :(得分:5)
由于主键密钥为ID, Type
,您可以使用聚合函数并确保查询仍然是确定性的,将查询减少为0个连接:
SELECT a.ID,
MAX(CASE WHEN a.type = 'First Name' THEN a.Data END) AS FirstName,
MAX(CASE WHEN a.type = 'Last Name' THEN a.Data END) AS LastName,
MAX(CASE WHEN a.type = 'Timestamp' THEN a.Data END) AS `Timestamp`,
MAX(CASE WHEN a.type = 'Count' THEN a.Data END) AS `Count`,
MAX(CASE WHEN a.type = 'MY_ID' THEN a.Data END) AS MY_ID,
MAX(CASE WHEN a.Type = 'Foreign Id' THEN a.Data END) AS ForeignId
FROM Attributes a
GROUP BY a.ID;
值得注意的是,实体 - 属性 - 值模型是一个SQL反模式,你可以更好地规范化数据以将属性存储为列,而不是必须使用上面的查询将行转换为列。
修改强>
要根据属性添加过滤器,请使用HAVING
子句:
SELECT a.ID,
MAX(CASE WHEN a.type = 'First Name' THEN a.Data END) AS FirstName,
MAX(CASE WHEN a.type = 'Last Name' THEN a.Data END) AS LastName,
MAX(CASE WHEN a.type = 'Timestamp' THEN a.Data END) AS `Timestamp`,
MAX(CASE WHEN a.type = 'Count' THEN a.Data END) AS `Count`,
MAX(CASE WHEN a.type = 'MY_ID' THEN a.Data END) AS MY_ID,
MAX(CASE WHEN a.Type = 'Foreign Id' THEN a.Data END) AS ForeignId
FROM Attributes a
GROUP BY a.ID
HAVING MAX(CASE WHEN a.type = 'MY_ID' THEN a.Data END) = 1;
答案 1 :(得分:0)
您的属性表很窄,但有很多行。并且您将要么进行一系列自连接,要么使用group by a.id
进行查询并使用聚合函数。后一种方法消除了连接,但仍然会产生很多行。
我认为更好的选择是对数据模型进行非规范化。这将涉及创建一个包含“First Name”列,“Middle Name”列等的表。然后,与ID关联的各种属性都在同一行。最终会得到一个更宽的表,但行数和连接数要少得多。