CREATE TABLE Attributes ( id VARCHAR(40), type VARCHAR(16), data VARCHAR(2048), PRIMARY KEY(id,type) );
This is the general format of query I am trying to run. The general idea is that 'objects' have unique ids and then have a key/value pair like javascript objects.
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'
In this query 'Foreign Id'
is an optional attribute. The problem is that I am getting
The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay.
I realize that I can do as said, but the warning worries me that this query is horribly inefficient. Is there a better way to formulate the query?
Since the primary key key is ID, Type
you can use aggregate functions and ensure the query is still deterministic, reducing the query to 0 joins:
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;
It is worth noting though that the Entity-Attribute-Value Model is an SQL Antipattern, and you could be much better off normalising your data to store the attributes as columns, rather than having to use the above query to turn rows into columns.
EDIT
To add a filter based on an attribute use the HAVING
clause:
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;