SQL JOIN query issue provides inaccurate return - mysql

I have spend hours searching for this specific issue on the site though many are close not address it completely. Please link it if it exists and I will happily take down this question.
I have two tables wb_states and wb_cities you can see by the keys:
composite state_code+country_code & city_id are distinctive for their respective tables.
OBJECTIVE: run a JOIN query to pull in the state_name from the wb_states table (in place of the state_code)
I always get the sql_mode=only_full_group_by ERROR unless I use the following
SELECT ANY_VALUE(c.city_id) as id,
ANY_VALUE(c.city_ascii) as ci,
ANY_VALUE(s.state_name_ascii) as ps,
ANY_VALUE(c.country_code) as co
FROM wb_cities AS c
JOIN wb_states AS s ON
s.state_code=c.state_code
WHERE c.city_ascii like 'aa%' GROUP BY id ORDER BY co,ps,ci ASC
Of course the query works but the moment we employ ANY_VALUE it fails.
Unique id 2959927 - city of Aalen belongs to only one province Baden-Wurttemberg. How do you construct this query? Thank you.
CREATE TABLE `wb_cities` (
`city_id` int(11) NOT NULL,
`city_name` varchar(65) DEFAULT NULL,
`city_ascii` varchar(65) DEFAULT NULL,
`state_code` varchar(55) DEFAULT NULL,
`state_name_ascii` varchar(45) DEFAULT NULL,
`country_code` varchar(45) DEFAULT NULL,
`country_full` varchar(55) DEFAULT NULL,
`lat` varchar(45) DEFAULT NULL,
`lon` varchar(45) DEFAULT NULL,
PRIMARY KEY (`city_id`)
)
CREATE TABLE `wb_states` (
`id` int(11) DEFAULT NULL,
`state_code` varchar(10) NOT NULL,
`state_name` varchar(45) DEFAULT NULL,
`state_name_ascii` varchar(45) DEFAULT NULL,
`country_code` varchar(45) NOT NULL,
PRIMARY KEY (`state_code`,`country_code`)
)
INSERT INTO `wb_cities` VALUES (14256,'Āzādshahr','Azadshahr','09','Hamadan','IR','Iran','34.79049','48.57011'),(18918,'Protaras','Protaras','01','Famagusta','CY','Cyprus','35.0125','34.05833'),(23814,'Kahrīz','Kahriz','13','Kermanshah','IR','Iran','34.3838','47.0553'),(24851,'Nūrābād','Nurabad','23','Lorestan','IR','Iran','34.0734','47.9725'),(32723,'Īstgāh-e Rāh Āhan-e Garmsār','Istgah-e Rah Ahan-e Garmsar','25','Semnan','IR','Iran','35.23455','52.30942'),(32767,'Qarchak','Qarchak','26','Tehran','IR','Iran','35.42867','51.57544'),(32909,'Shahre Jadide Andisheh','Shahre Jadide Andisheh','26','Tehran','IR','Iran','35.6803','51.0193'),(41210,'Khorramdarreh','Khorramdarreh','36','Zanjan Province','IR','Iran','36.20898','49.19152'),(50672,'Wanlaweyn','Wanlaweyn','14','Shabeellaha Hoose','SO','Somalia','2.6185','44.8938'),(52867,'Qoryooley','Qoryooley','14','Shabeellaha Hoose','SO','Somalia','1.78784','44.52999');
INSERT INTO `wb_states` VALUES (29,'00','Armenia','Armenia','AM'),(11,'00','Aruba','Aruba','AW'),(15,'00','Bosnia and Herzegovina','Bosnia and Herzegovina','BA'),(31,'00','Botswana','Botswana','BW'),(7,'00','Belarus','Belarus','BY'),(23,'00','Cook Islands','Cook Islands','CK'),(39,'00','Christmas Island','Christmas Island','CX'),(4,'00','Czech Republic','Czech Republic','CZ'),(17,'00','Western Sahara','Western Sahara','EH'),(10,'00','Falkland Islands (Islas Malvinas)','Falkland Islands (Islas Malvinas)','FK'),(26,'00','Abkhazia','Abkhazia','GE'),(27,'00','Ghana','Ghana','GH'),(37,'00','Gibraltar','Gibraltar','GI'),(3,'00','Equatorial Guinea','Equatorial Guinea','GQ'),(16,'00','South Georgia and The South Sandwich Islands','South Georgia and The South Sandwich Islands','GS'),(28,'00','Hong Kong','Hong Kong','HK'),(6,'00','Indonesia','Indonesia','ID'),(8,'00','Ireland','Ireland','IE'),(32,'00','Kyrgyzstan','Kyrgyzstan','KG'),(36,'00','Comoros','Comoros','KM'),(34,'00','Muḩāfaz̧atalWafrah','MuhafazatalWafrah','KW'),(19,'00','Zhezqazghan Oblysy','Zhezqazghan Oblysy','KZ'),(21,'00','Lithuania','Lithuania','LT'),(40,'00','Monaco','Monaco','MC'),(13,'00','Montenegro','Montenegro','ME'),(9,'00','Mali','Mali','ML'),(5,'00','Macedonia','Macedonia','MO'),(35,'00','Mauritius','Mauritius','MU'),(25,'00','Malaysia','Malaysia','MY'),(41,'00','Norfolk Island','Norfolk Island','NF'),(30,'00','Bāgmatī Zone','Bagmati Zone','NP'),(2,'00','Niue','Niue','NU'),(14,'00','Panama','Panama','PA'),(22,'00','Philippines','Philippines','PH'),(42,'00','Palestine','Palestine','PS'),(43,'00','Serbia','Serbia','RS'),(24,'00','Swaziland','Swaziland','SZ'),(20,'00','Turks and Caicos Islands','Turks and Caicos Islands','TC'),(33,'00','Turkmenistan','Turkmenistan','TM'),(38,'00','Turkey','Turkey','TR'),(12,'00','British Virgin Islands','British Virgin Islands','VG'),(18,'00','Zimbabwe','Zimbabwe','ZW'),(164,'01','Abū Z̧aby','Abu Zaby','AE'),(90,'01','Badakhshan','Badakhshan','AF'),(112,'01','Barbuda','Barbuda','AG'),(118,'01','Aragatsotn','Aragatsotn','AM'),(124,'01','Benguela','Benguela','AO'),(45,'01','Buenos Aires','Buenos Aires','AR'),(146,'01','Burgenland','Burgenland','AT');

You join wb_cities to wb_states only on state_code but you should also use country_code, because state_code is not unique in wb_states.
Also I don't see any reason for aggregation. You need only a join of the tables:
SELECT c.city_id id,
c.city_ascii ci,
s.state_name_ascii ps,
c.country_code co
FROM wb_cities AS c JOIN wb_states AS s
ON s.state_code=c.state_code AND s.country_code = c.country_code
WHERE c.city_ascii like 'aa%'
ORDER BY co, ps, ci

Your data model is broken. Here are two definitions of state_code:
`state_code` varchar(55)
`state_code` varchar(10)
And yet this is part of an undeclared foreign key relationship.
I think this is the root problem:
PRIMARY KEY (`state_code`, `country_code`)
Presumably, the ID is unique, so you should have:
CREATE TABLE `wb_states` (
`state_id` int(11) DEFAULT PRIMARY KEY,
`state_code` varchar(10) NOT NULL,
`state_name` varchar(45) DEFAULT NULL,
`state_name_ascii` varchar(45) DEFAULT NULL,
`country_code` varchar(45) NOT NULL,
`country_full` varchar(55) DEFAULT NULL,
UNIQUE (`state_code`,`country_code`)
);
Then, your wb_cities table can be appropriately defined as:
CREATE TABLE `wb_cities` (
`city_id` int(11) NOT NULL PRIMARY KEY,
`city_name` varchar(65) DEFAULT NULL,
`city_ascii` varchar(65) DEFAULT NULL,
`state_id` int DEFAULT NULL,
`lat` varchar(45) DEFAULT NULL,
`lon` varchar(45) DEFAULT NULL,
PRIMARY KEY (`city_id`),
FOREIGN KEY (state_id) REFERENCES wb_states(state_id)
);
You should probably have a "countries" table as well, but at least the country can go in the "states" table rather than the "cities" table.
Then, the "state" information can be looked up using the state_id.
After you have fixed the data model, you can think about fixing the query.

Related

Avoid INSERT when the combination of First name and Last already exists - MYSQL

newbie and appreciate your help.
So I have the below employee table with emp_id as primary and auto incremental. I would like to avoid users from inserting new record when the combination of first_name and last_name already exists.
I am connecting the DB to windows from (VB.net), ultimately I would like to display a message saying that the user's first and last name already exists. I could do it progrmaticly by vb code, however i am wondering if I can setup this check at the database level.
CREATE TABLE `employee` (
`emp_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(20) NOT NULL,
`middle_name` varchar(30) DEFAULT NULL,
`last_name` varchar(20) NOT NULL,
`date_of_birth` varchar(45) NOT NULL,
`gender` char(6) NOT NULL,
PRIMARY KEY (`emp_id'),
UNIQUE KEY `employee_id_UNIQUE` (`emp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
You can make constraints on sets of columns like this:
CREATE TABLE `employee` (
`emp_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(20) NOT NULL,
`middle_name` varchar(30) DEFAULT NULL,
`last_name` varchar(20) NOT NULL,
`date_of_birth` varchar(45) NOT NULL,
`gender` char(6) NOT NULL,
PRIMARY KEY (`emp_id'),
UNIQUE KEY `employee_name_UNIQUE` (`first_name`, `last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
That means if the combination of first_name and last_name already exists in the database, if you try to insert a new row with the same values, it results in a duplicate key error.
You need to write code in your application to handle that error, and then display an appropriately helpful message to the user.

mysql workbench duplicate key error

I have a data set with a list of country names, and the country names are repeated once for "Males" and then again for "Females".
For example:
c_name gender
China M
Greece M
Algeria M
China F
Greece F
Algeria F
When I create table and import data from a csv file, I get a 'duplicate key' error. I am wondering if this has anything to do with the engine settings? Any ideas how this can be resolved? (I know it works because my friend got it to work on her Mac, and she did not have the option to choose 'Collate' or 'Engine' when creating her tables, but I'm on Windows)
EDIT: Here's how I'm creating the table:
CREATE TABLE dbs.enrollment (
e_id INT NOT NULL,
c_name VARCHAR(45) NOT NULL,
gender VARCHAR(45) NULL,
2001 INT NULL,
2002 INT NULL,
2003 INT NULL,
2004 INT NULL,
2005 INT NULL,
2006 INT NULL,
2007 INT NULL,
2008 INT NULL,
2009 INT NULL,
2010 INT NULL,
PRIMARY KEY (e_id, c_name));
Your friend might set a primary key with c_name in this table ,if you want to have a change ,you can cancel the primary key。
It would be better to answer if you shared the query which is used for the above. I agree with Walker Li.
If your query is something like this..
CREATE TABLE enrollment (
c_name VARCHAR(255) NOT NULL,
gender VARCHAR(255) NOT NULL,
PRIMARY KEY (c_name)
);
You can change it by removing the primary id line as
CREATE TABLE enrollment (
c_name VARCHAR(255) NOT NULL,
gender VARCHAR(255) NOT NULL
);
Hope this solves your problem.
If your csv data contains any unique column as ID you could use it as primary key as,
CREATE TABLE enrollment (
e_id INT NOT NULL,
gender VARCHAR(255) NOT NULL,
PRIMARY KEY (e_id)
);
A table can have only one primary key. Remove c_name in the last line and only have e_id as shown below
PRIMARY KEY (e_id);
The combination of e_id and c_name must be unique. If not you can create an additional artifical primary key as work around.
CREATE TABLE `enrollment` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`e_id` int(11) NOT NULL,
`c_name` varchar(45) NOT NULL,
`gender` varchar(45) DEFAULT NULL,
`2001` int(11) DEFAULT NULL,
`2002` int(11) DEFAULT NULL,
`2003` int(11) DEFAULT NULL,
`2004` int(11) DEFAULT NULL,
`2005` int(11) DEFAULT NULL,
`2006` int(11) DEFAULT NULL,
`2007` int(11) DEFAULT NULL,
`2008` int(11) DEFAULT NULL,
`2009` int(11) DEFAULT NULL,
`2010` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

MySQL Left join take too long for huge data

I have two tables .Property tables and it related photo.One property may have many photo but I want only one any of it related photo, When I use left join MySQL query it become too slow.
Here is my query
SELECT `sp_property`.`id` as propertyid, `sp_property`.`property_name`, `sp_property`.`property_price`, `sp_property`.`adv_type`, `sp_property`.`usd`, `images`.`filepath_name`
FROM (`sp_property`)
LEFT JOIN (select id, Max(property_id) as pid,filepath_name
from sp_property_images
group by property_id) `images`
ON `images`.`pid` = `sp_property`.`id`
WHERE `sp_property`.`published` = 'yes'
GROUP BY `propertyid`
ORDER BY `sp_property`.`feature_listing` desc, `submit_date` desc
LIMIT 1,20
CREATE TABLE IF NOT EXISTS `sp_property_images` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`property_id` varchar(100) NOT NULL,
`filepath_name` text,
`label_name` varchar(45) DEFAULT NULL,
`primary` char(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `property_id` (`property_id`),
KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=12941 ;
CREATE TABLE IF NOT EXISTS `sp_property` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`propertytype` varchar(50) NOT NULL,
`adv_type` varchar(45) NOT NULL,
`property_name` text,
`division` varchar(45) NOT NULL,
`township` varchar(45) NOT NULL,
`property_price` decimal(20,2) unsigned DEFAULT NULL,
`price_type` varchar(45) NOT NULL,
`availability` varchar(100) DEFAULT NULL,
`property_address` text,
`p_dimension_length` varchar(45) NOT NULL,
`p_dimension_width` varchar(45) NOT NULL,
`p_dimension_sqft` varchar(45) NOT NULL,
`p_dimension_acre` varchar(45) NOT NULL,
`floor` varchar(45) NOT NULL,
`phone` varchar(100) DEFAULT NULL,
`aircorn` varchar(45) NOT NULL,
`ownership` varchar(45) NOT NULL,
`bedroom` varchar(45) NOT NULL,
`bathroom` varchar(45) NOT NULL,
`special_feature` text,
`amentites` text,
`property_detail` text,
`submit_date` datetime DEFAULT NULL,
`published` varchar(45) NOT NULL,
`published_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`agent_id` varchar(45) NOT NULL,
`source` varchar(45) NOT NULL,
`contact_name` varchar(100) NOT NULL,
`contact_no` varchar(100) NOT NULL,
`contact_address` text NOT NULL,
`contact_email` varchar(100) NOT NULL,
`unit_type` varchar(100) DEFAULT NULL,
`map_lat` varchar(100) DEFAULT NULL,
`map_long` varchar(100) DEFAULT NULL,
`show_map` varchar(3) DEFAULT 'no',
`total_view` bigint(20) NOT NULL DEFAULT '0',
`feature_listing` varchar(10) NOT NULL DEFAULT 'no',
`new_homes_id` int(11) NOT NULL,
`publish_price` int(1) NOT NULL DEFAULT '0',
`usd` decimal(20,2) NOT NULL,
`tag_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=18524 ;
Have you added indices on your tables? You would need three indices on the following columns:
article_photo.a_id for grouping and joining
article_photo.p_id for sorting
article.a_id for joining (although this is hopefully already the PK of your table)
The result of joins is not guaranteed to be sorted in any order, so you probably want to move your ORDER BY clause from the subquery to the outer query:
SELECT * from `article`
LEFT JOIN (
SELECT * from `article_photo`
GROUP BY `a_id`) as images
ON article.a_id = images.a_id
ORDER BY images.p_id DESC
Also, you have no guarantee on which article_photo you will get, since select data without an aggregate function (and only MySQL will allow you to do that).
Now that the question contains the real tables and all information essential to answering, here's my take – first, here's your query:
SELECT `sp_property`.`id` as propertyid, `sp_property`.`property_name`, `sp_property`.`property_price`, `sp_property`.`adv_type`, `sp_property`.`usd`, `images`.`filepath_name`
FROM (`sp_property`)
LEFT JOIN (select id, Max(property_id) as pid,filepath_name
from sp_property_images
group by property_id) `images`
ON `images`.`pid` = `sp_property`.`id`
WHERE `sp_property`.`published` = 'yes'
GROUP BY `propertyid`
ORDER BY `sp_property`.`feature_listing` desc, `submit_date` desc
LIMIT 1,20
Let's see. you are joining sp_property_images.property_id with sp_property.id. These columns have different types (int vs. varchar) and I suppose this results in a severe performance penalty (since the values have to be converted to the same type).
Then, you are filtering by sp_property.published, so I suggest adding an index on this column as well. Also, examine if you really need to have this column as varchar. A bool/bit flag probably suffices as well (if it doesn't, an enum might be a better choice still).
Ordering benefits from an index too. Add an index spanning both columns sp_property.feature_listing and sp_property.submit_date.
If all of the above still doesn't help, you might have to remove the sub-select. It might prevent the mysql engine from recognizing (and using!) the index you have defined on the sp_property_images.property_id column.
This simple query will give you what you asked for, all articles with their photos
SELECT ar.a_id, ar.a_title, ap.p_id, ap.photo_name
FROM article ar
JOIN article_photo ap on ar.a_id = ap.a_id
No reason for left join and grouping there or you wanna get sum on photos by article?

How to select column twice from the same mysql table?

I've been doing quite a bit of MySql lately for uni, and i cant seem to figure out how to get a field from a table twice in the same statement.
My database is this:
drop database if exists AIRLINE;
create database AIRLINE;
use AIRLINE;
CREATE TABLE AIRCRAFT
(
AircraftNo INT(20) NOT NULL,
AircraftType VARCHAR(100) NOT NULL,
FuelBurn VARCHAR(100) NOT NULL,
Airspeed VARCHAR(100) NULL,
LastInspection DATE NULL,
TotalFlyingTime INT(50) NOT NULL,
TotalTimeLeftEngine INT(50) NULL,
TotalTimeRightEngine INT(50) NULL,
PRIMARY KEY (AircraftNo)
);
CREATE TABLE PILOT
(
PilotCode INT(20) NOT NULL,
LastName VARCHAR(100) NOT NULL,
FirstName VARCHAR(100) NOT NULL,
MiddleInitial VARCHAR(50) NULL,
HiredDate DATE NULL,
BasePay VARCHAR(50) NULL,
Dependents VARCHAR(100) NULL,
License INT(50) NOT NULL,
TotalHours INT(50) NOT NULL,
PRIMARY KEY (PilotCode)
);
CREATE TABLE CUSTOMER
(
CustomerNo INT(20) NOT NULL,
Name VARCHAR(100) NOT NULL,
Contact INT(50) NOT NULL,
Phone INT(50) NOT NULL,
Street VARCHAR(100) NULL,
Suburb VARCHAR(100) NULL,
State VARCHAR(100) NULL,
Postcode INT(20) NULL,
Balance INT(50) NULL,
PRIMARY KEY (CustomerNo)
);
CREATE TABLE CHARTER
(
TripTicket INT(50) NOT NULL AUTO_INCREMENT,
CharterDate DATE NOT NULL,
PilotCode INT(20) NOT NULL,
CopilotCode INT(20) NULL,
AircraftNo INT(20) NOT NULL,
Destination VARCHAR(100) NOT NULL,
Distance INT(20) NULL,
HoursFlow INT(20) NULL,
HoursWating INT(20) NULL,
Fuel INT(20) NULL,
Oil INT(20) NULL,
CustomerNo INT(20) NOT NULL,
PRIMARY KEY (TripTicket),
FOREIGN KEY(PilotCode) REFERENCES PILOT(PilotCode),
FOREIGN KEY(CopilotCode) REFERENCES PILOT(PilotCode),
FOREIGN KEY(AircraftNo) REFERENCES AIRCRAFT(AircraftNo),
FOREIGN KEY(CustomerNo) REFERENCES CUSTOMER(CustomerNo)
);
My goal is to list the charterdate, destination, customer details (name, customerNo, address, phone), and pilot names (firstname, middleinitial, lastname) of all charters.
I have managed to get everything, but only with one pilot. I need to list both pilot names however.
I have googled my problem, but i cant seem to find anything.
If someone could please point me in the right direction, i would be hugely grateful.
Thanks
Cheers
Corey
You just need to JOIN the table twice with different aliases.
Something like:
SELECT p1.lastname, p2.lastname, /* other fields */
FROM CHARTER c
JOIN PILOT p1 ON p1.PilotCode = c.PilotCode
JOIN PILOT p2 on p2.PilotCode = c.CoPilotCode
Give alias name as
SELECT a.columname1 AS 1, a.columname1 AS 2
FROM tablename a
You have to use table aliases in your join:
SELECT MainPilot.LastName, CoPilot.LastName FROM CHARTER
LEFT JOIN PILOT MainPilot ON MainPilot.PilotCode=CHARTER.PilotCode
LEFT JOIN PILOT CoPilot ON CoPilot.PilotCode=CHARTER.CoPilotCode
You need to join the pilot table twice in your query. to do that you will have to use an alias for each Pilot table you join.
You can simply use the same column multiple times and add for each of them and as and use different name
SELECT column1 as c1, column1 as c2, column1 as c3 FROM TABLE1 WHERE ....

Data Structure causing impossible joins

Tables:
nodes
data_texts
data_profiles
data_locations
data_profiles
data_media
data_products
data_metas
categories
tags
categories_nodes
tags_nodes
This question is a generalized question and is on the back of another question
Explanation:
Each of the "data" tables has a node_id that refers back to the id of the nodes table (hasMany/belongsTo association).
A "Node" can be anything - a TV Show, a Movie, a Person, an Article...etc (all generated via a CMS, so the user can control what type of "Nodes" they want).
When pulling data, I want to be able to query against certain fields. For example if they do a search, I want to be able to pull nodes that have data_texts.title = '%george%' or order by the datetime field in data_locations.
The problem is, when I do a join on all seven data tables (or more), the query has to hit so many combined rows that it just times out (even with a nearly empty database.... total 200 rows across the entire database).
I realize I can determine IF I need a join depending on what I'm doing - but even with five or six joins (once the database gets to 10k+ records), it's going to be horribly slow, if it works at all. Per this question, the query I'm using just doing a join on these tables times out completely.
Each node can have multiple rows of each data type (for multi-language reasons among others).
I'm completely defeated - I'm at the point where I think I need to restructure the entire thing, but don't have the time for that. I've thought about combining all into one table, but aren't sure how....etc
nodes
CREATE TABLE `nodes` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`slug` VARCHAR(100) NOT NULL,
`node_type_id` CHAR(36) NOT NULL,
`site_id` CHAR(36) NOT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `nodeTypeId` (`node_type_id`),
INDEX `slug` (`slug`),
INDEX `nodeId` (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM;
data_texts:
CREATE TABLE `data_texts` (
`id` CHAR(36) NOT NULL,
`title` VARCHAR(250) NULL DEFAULT NULL,
`subtitle` VARCHAR(500) NULL DEFAULT NULL,
`content` LONGTEXT NULL,
`byline` VARCHAR(250) NULL DEFAULT NULL,
`language_id` CHAR(36) NULL DEFAULT NULL,
`foreign_key` CHAR(36) NULL DEFAULT NULL,
`model` VARCHAR(40) NULL DEFAULT NULL,
`node_id` CHAR(36) NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `nodeId` (`node_id`),
INDEX `languageId_nodeId` (`language_id`, `node_id`),
INDEX `foreignKey_model` (`foreign_key`, `model`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
data_profiles
CREATE TABLE `data_profiles` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(80) NULL DEFAULT NULL,
`email_personal` VARCHAR(100) NULL DEFAULT NULL,
`email_business` VARCHAR(100) NULL DEFAULT NULL,
`email_other` VARCHAR(100) NULL DEFAULT NULL,
`title` VARCHAR(100) NULL DEFAULT NULL,
`description` LONGTEXT NULL,
`prefix` VARCHAR(40) NULL DEFAULT NULL,
`phone_home` VARCHAR(40) NULL DEFAULT NULL,
`phone_business` VARCHAR(40) NULL DEFAULT NULL,
`phone_mobile` VARCHAR(40) NULL DEFAULT NULL,
`phone_other` VARCHAR(40) NULL DEFAULT NULL,
`foreign_key` CHAR(36) NULL DEFAULT NULL,
`model` VARCHAR(40) NULL DEFAULT NULL,
`node_id` CHAR(36) NULL DEFAULT NULL,
`language_id` CHAR(36) NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
`user_id` CHAR(36) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `nodeId` (`node_id`),
INDEX `languageId_nodeId` (`node_id`, `language_id`),
INDEX `foreignKey_model` (`foreign_key`, `model`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM;
categories
CREATE TABLE `categories` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(100) NOT NULL,
`node_type_id` CHAR(36) NOT NULL,
`site_id` CHAR(36) NOT NULL,
`slug` VARCHAR(100) NOT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `nodeTypeId` (`node_type_id`),
INDEX `slug` (`slug`)
)
COMMENT='Used to categorize nodes'
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
categories_nodes
CREATE TABLE `categories_nodes` (
`id` CHAR(36) NOT NULL,
`category_id` CHAR(36) NOT NULL,
`node_id` CHAR(36) NOT NULL,
PRIMARY KEY (`id`),
INDEX `categoryId_nodeId` (`category_id`, `node_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
node_tags
CREATE TABLE `node_tags` (
`id` CHAR(36) NOT NULL,
`name` VARCHAR(40) NOT NULL,
`site_id` CHAR(36) NOT NULL,
`created` DATETIME NOT NULL,
`modified` DATETIME NOT NULL,
PRIMARY KEY (`id`),
INDEX `siteId` (`site_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
nodes_node_tags
CREATE TABLE `nodes_node_tags` (
`id` CHAR(36) NOT NULL,
`node_id` CHAR(36) NOT NULL,
`node_tag_id` CHAR(36) NOT NULL,
PRIMARY KEY (`id`),
INDEX `node_id_node_tag_id` (`node_id`, `node_tag_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;
MySQL:
SELECT `Node`.`id`, `Node`.`name`, `Node`.`slug`, `Node`.`node_type_id`, `Node`.`site_id`, `Node`.`created`, `Node`.`modified`
FROM `mysite`.`nodes` AS `Node`
LEFT JOIN `mysite`.`data_date_times` AS `DataDateTime` ON (`DataDateTime`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_locations` AS `DataLocation` ON (`DataLocation`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_media` AS `DataMedia` ON (`DataMedia`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_metas` AS `DataMeta` ON (`DataMeta`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_profiles` AS `DataProfile` ON (`DataProfile`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_products` AS `DataProduct` ON (`DataProduct`.`node_id` = `Node`.`id`)
LEFT JOIN `mysite`.`data_texts` AS `DataText` ON (`DataText`.`node_id` = `Node`.`id`)
WHERE 1=1
GROUP BY `Node`.`id`
Firstly, try InnoDB, not MyISAM.
Secondly, remove the group by, see how well it runs then, and how many rows are involved. Shouldn't be that many, but it's interesting.
You don't need the 'nodeId' index on node (as you already have it as a primary key). Again, shouldn't make any difference.
The where clause is irrelevant. You can remove it with no effect one way or another.
Thirdly, well, something is seriously broken.
Have a quick look on how to start profiling (e.g. http://dev.mysql.com/doc/refman/5.0/en/show-profile.html) , and run a profile command to see where all the time is going. Post it here if it doesn't immediately show that something is broken.
I'm unfortunately not in a position where I can do any tests right now. I'll just throw out some ideas. I might be able to do some tests later.
Be suspicious of different collations.
Some of your ids are useless. For example, you should drop the column categories_nodes.id, and put a primary key constraint on {category_id, node_id} instead.
Be suspicious of any design that requires joining all the tables at run time. There are better ways.
Use innodb and foreign key constraints.