I checked the suggested posts but couldn't find an answer. I am making a CRUD application with a many to many relationship and three MySQL tables. One table is called "pm":
CREATE TABLE `pm` (
`pm_id` int(11) NOT NULL AUTO_INCREMENT,
`pm_name` varchar(45) NOT NULL,
`pm_address` varchar(45) DEFAULT NULL,
`valid_through` int(11) NOT NULL,
PRIMARY KEY (`pm_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
+-------+---------+------------------------+---------------+
| pm_id | pm_name | pm_address | valid_through |
+-------+---------+------------------------+---------------+
| 1 | Alpha | http://www.alpha.com | 190303 |
| 2 | Bravo | http://www.bravo.com | 200506 |
| 3 | Charlie | http://www.charlie.com | 190708 |
| 4 | Delta | http://www.delta.com | 210509 |
| 5 | Echo | http://www.echo.com | 230416 |
| 6 | Foxtrot | http://www.foxtrot.com | 181011 |
+-------+---------+------------------------+---------------+
Another is called "searchwords":
CREATE TABLE `searchwords` (
`searchword_id` int(11) NOT NULL AUTO_INCREMENT,
`searchword` varchar(45) NOT NULL,
PRIMARY KEY (`searchword_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
+---------------+------------+
| searchword_id | searchword |
+---------------+------------+
| 1 | apples |
| 2 | oranges |
| 3 | pears |
| 4 | bananas |
| 5 | grapes |
+---------------+------------+
The third is join_table:
CREATE TABLE `join_table` (
`id_join_table` int(11) NOT NULL AUTO_INCREMENT,
`pm_id` int(11) DEFAULT NULL,
`searchword_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id_join_table`),
KEY `FK1_idx` (`pm_id`),
KEY `FK2_idx` (`searchword_id`),
CONSTRAINT `FK1` FOREIGN KEY (`pm_id`) REFERENCES `pm` (`pm_id`) ON DELETE
NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK2` FOREIGN KEY (`searchword_id`) REFERENCES `searchwords`
(`searchword_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
+---------------+-------+---------------+
| id_join_table | pm_id | searchword_id |
+---------------+-------+---------------+
| 8 | 6 | NULL |
| 9 | 6 | NULL |
| 10 | 6 | NULL |
+---------------+-------+---------------+
Below is the SQL I have now. With for instance "oranges" at the end I want to get - into one new row of "join_table" - the max pm_id from "pm" into the pm_id column and the searchword_id that corresponds to oranges from "searchwords" into the searchword_id column.
INSERT INTO join_table (pm_id, searchword_id)
SELECT (SELECT MAX(pm_id) FROM pm), (SELECT DISTINCT
searchwords.searchword_id FROM searchwords
INNER JOIN join_table ON
searchwords.searchword_id = join_table.searchword_id
WHERE searchword = "oranges");
This SQL has magically worked sometimes but usually not (how is that kind of inconsistency even possible?). The pm_id value always gets in there so I tend to get a row with the correct value as pm_id and searchword as NULL as seen above.
Help would be much appreciated!!
Actually I just solved it, using:
INSERT INTO join_table (pm_id, searchword_id)
SELECT MAX(pm_id), searchword_id
FROM pm, searchwords
WHERE searchword="bananas"
Inner joins are so 2017 anyway, right?
But now I'm having problems when trying to delete a post and got an error:
Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint
violation: 1451 Cannot delete or update a parent row: a foreign key
constraint fails (`database`.`join_table`, CONSTRAINT `FK1`
FOREIGN KEY (`pm_id`) REFERENCES `pm` (`pm_id`)
Sigh
Related
I need to optimize the following query:
SELECT a.*
FROM Activity AS a
JOIN users_following AS f1
ON f1.userId = a.originatorId
AND f1.followerId = 1
ORDER
BY a.time DESC
LIMIT 10
The idea is to get all activity originated by users some user (in this case, user 1) is following, sorted by time. This query as written is very slow (~5s), though it's very quick if either a) the join is omitted or b) the order by clause is omitted.
Things I've tried:
WHERE ... IN as opposed to INNER JOIN
Here are the CREATE TABLE and EXPLAIN definitions.
CREATE TABLE `Activity` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`time` int(11) NOT NULL,
`userId` int(11) NOT NULL,
`voteId` int(11) DEFAULT NULL,
`commentId` int(11) DEFAULT NULL,
`achievementId` int(11) DEFAULT NULL,
`challengeId` int(11) DEFAULT NULL,
`followerId` int(11) DEFAULT NULL,
`acknowledged` int(11) NOT NULL DEFAULT '0',
`type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`isPrivate` int(11) NOT NULL DEFAULT '0',
`portalId` int(11) DEFAULT NULL,
`postId` int(11) DEFAULT NULL,
`portalMemberId` int(11) DEFAULT NULL,
`originatorId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_55026B0C1CC880D8` (`portalMemberId`),
KEY `IDX_55026B0C1D79C36A` (`challengeId`),
KEY `IDX_55026B0CE7A069D0` (`achievementId`),
KEY `IDX_55026B0CB6FEC0EE` (`voteId`),
KEY `IDX_55026B0C6690C3F5` (`commentId`),
KEY `IDX_55026B0C64B64DCC` (`userId`),
KEY `IDX_55026B0CF542AA03` (`followerId`),
KEY `IDX_55026B0C57076B1F` (`portalId`),
KEY `IDX_55026B0CE094D20D` (`postId`),
KEY `IDX_55026B0C162E014D` (`originatorId`),
KEY `activity_time_idx` (`time`),
KEY `activity_filter_idx` (`type`,`originatorId`,`userId`,`isPrivate`),
KEY `acknowledged_idx` (`acknowledged`),
KEY `idx1` (`time`,`originatorId`),
KEY `idx2` (`originatorId`,`userId`,`postId`,`challengeId`,`commentId`,`time`),
CONSTRAINT `FK_55026B0C162E014D` FOREIGN KEY (`originatorId`) REFERENCES `ProseUser` (`id`),
CONSTRAINT `FK_55026B0C1CC880D8` FOREIGN KEY (`portalMemberId`) REFERENCES `PortalMember` (`id`),
CONSTRAINT `FK_55026B0C1D79C36A` FOREIGN KEY (`challengeId`) REFERENCES `Challenge` (`id`),
CONSTRAINT `FK_55026B0C57076B1F` FOREIGN KEY (`portalId`) REFERENCES `Portal` (`id`),
CONSTRAINT `FK_55026B0C64B64DCC` FOREIGN KEY (`userId`) REFERENCES `ProseUser` (`id`),
CONSTRAINT `FK_55026B0C6690C3F5` FOREIGN KEY (`commentId`) REFERENCES `Comment` (`id`),
CONSTRAINT `FK_55026B0CB6FEC0EE` FOREIGN KEY (`voteId`) REFERENCES `Vote` (`id`),
CONSTRAINT `FK_55026B0CE094D20D` FOREIGN KEY (`postId`) REFERENCES `Post` (`id`),
CONSTRAINT `FK_55026B0CE7A069D0` FOREIGN KEY (`achievementId`) REFERENCES `UserAchievement` (`id`),
CONSTRAINT `FK_55026B0CF542AA03` FOREIGN KEY (`followerId`) REFERENCES `ProseUser` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4097200 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ;
CREATE TABLE `users_following` (
`userId` int(11) NOT NULL,
`followerId` int(11) NOT NULL,
PRIMARY KEY (`userId`,`followerId`),
KEY `IDX_17C2F70264B64DCC` (`userId`),
KEY `IDX_17C2F702F542AA03` (`followerId`),
KEY `idx1` (`userId`,`followerId`),
KEY `idx2` (`followerId`,`userId`),
CONSTRAINT `FK_17C2F70264B64DCC` FOREIGN KEY (`userId`) REFERENCES `ProseUser` (`id`),
CONSTRAINT `FK_17C2F702F542AA03` FOREIGN KEY (`followerId`) REFERENCES `ProseUser` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
EXPLAIN
+----+-------------+-------+------------+------+-------------------------------------------------------------+----------------------+---------+---------------------------+------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------------------------------------------------+----------------------+---------+---------------------------+------+----------+----------------------------------------------+
| 1 | SIMPLE | f1 | NULL | ref | PRIMARY,IDX_17C2F70264B64DCC,IDX_17C2F702F542AA03,idx1,idx2 | IDX_17C2F702F542AA03 | 4 | const | 145 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | a | NULL | ref | IDX_55026B0C162E014D,idx2 | IDX_55026B0C162E014D | 5 | prose_2_24_2021.f1.userId | 38 | 100.00 | NULL |
+----+-------------+-------+------------+------+-------------------------------------------------------------+----------------------+---------+---------------------------+------+----------+----------------------------------------------+
Let's make an example: user #1 follows users #2 and #3. Here are activities ordered by users, then time:
+------+-------+
| user | time |
+------+-------+
| 1 | 10:00 |
| 1 | 11:00 |
| 2 | 10:00 |
| 2 | 12:00 |
| 3 | 09:00 |
| 3 | 13:00 |
| 4 | 10:00 |
+------+-------+
We can quickly find the followed users' activities, but get the times unordered:
+------+-------+
| user | time |
+------+-------+
| 2 | 10:00 |
| 2 | 12:00 |
| 3 | 09:00 |
| 3 | 13:00 |
+------+-------+
This means that we must sort them in order to get the top n sorted. And if these were not four but thousands or millions of activities that would take awfully long.
If on the other hand the data were available ordered by time descending, then user:
+------+-------+
| user | time |
+------+-------+
| 3 | 13:00 |
| 2 | 12:00 |
| 1 | 11:00 |
| 1 | 10:00 |
| 2 | 10:00 |
| 4 | 10:00 |
| 3 | 09:00 |
+------+-------+
We would have to read the whole data sequentially until we found the n top activities. No further ordering necessary. If we are lucky the first n rows are matches and that's it. If we are unlucky we read the whole table (or index for that matter).
So, there is no guarantee to get this quick. The first approach gets the data quick, but sorting can take long. The second approach needs no sorting, but reading can take long.
I like the second approach a tad better, but it all depends on the data of course. Are there many users? Is the majority followed by user #1 or only few? Are there many activities? Many by few users or few activities per user? ... Anyway, I'd provide this index:
create index idx1 on activity (time desc, originatorid);
As an index is just an offer to the DBMS we might just as well provide the other index for the case the DBMS wants to follow the other route:
create index idx2 on activity (originatorid, time desc);
And this is how I'd probably write the query:
SELECT a.*
FROM activity AS a
WHERE EXISTS
(
SELECT NULL
FROM users_following AS f1
WHERE f1.userId = a.originatorId
AND f1.followerId = 1
)
ORDER BY a.time DESC
LIMIT 10;
We have the following table and we ran into an issue that our unique key is not working (as expected).
CREATE TABLE `documentation_photos` (
`commissionID` smallint(5) unsigned NOT NULL,
`periodID` smallint(5) unsigned NOT NULL,
`carreirID` int(11) NOT NULL,
`groupID` smallint(5) unsigned DEFAULT NULL,
`order` tinyint(4) NOT NULL,
`file` varchar(200) NOT NULL,
UNIQUE KEY `idZak_UNIQUE` (`commissionID`,`periodID`,`carreirID`,`groupID`,`order`),
KEY `ncis & obdobi & idZak` (`commissionID`,`periodID,`carreirID``),
KEY `fotodoc_skupina` (`idSkup`),
CONSTRAINT `fotodoc_` FOREIGN KEY (`groupID`) REFERENCES `groups` (`groupID`),
CONSTRAINT `fotodoc_zaknos` FOREIGN KEY (`commissionID`, `periodID`, `carreirID`) REFERENCES `carrier_of_commission` (`commissionID`, `periodID`, `carreirID`) ON DELETE CASCADE
);
I saw the issue, that describes that NULL is considered unique every time it occurs, but it causes a lot of problems for us. The only one I found was for Postgres...
|--------------|----------|-----------|---------|-------|---------|
| commissionID | periodID | carrierID | groupID | order | file |
|--------------|----------|-----------|---------|-------|---------|
| 1140 | 117 | 2235 | null | 1 | photo-1 |
|--------------|----------|-----------|---------|-------|---------|
| 1140 | 117 | 2235 | null | 1 | photo-1 | -- This is duplicate
|--------------|----------|-----------|---------|-------|---------|
| 1140 | 117 | 2235 | null | 2 | photo-2 |
|--------------|----------|-----------|---------|-------|---------|
| 1140 | 117 | 2235 | null | 1 | photo-1 | -- This is duplicate
|--------------|----------|-----------|---------|-------|---------|
I want to treat null as a single value.
We would like to have working unique/primary key and keep the foreign key if possible.
Is there some known solution for this in MySQL?
Each NULL is unique (two NULLs are not equal) - the row which contains NULL in index expression is not checked for uniqueness, the row which contains NULL in FK expressions is not checked for reference integrity.
Is there some known solution for this in MySQL?
Use generated column which replaces NULL with some definite but logically impossible literal value, use this column in index/FK expression instead of nullale column.
I have the following schema in MySQL:
CREATE TABLE `ORDER_CONTENTS` (
`Order_ID` int(10) NOT NULL,
`Pizza_Name` varchar(20) NOT NULL DEFAULT '',
`Quantity` int(2) NOT NULL,
PRIMARY KEY (`Order_ID`,`Pizza_Name`),
KEY `ordercontentsfk2_idx` (`Pizza_Name`),
CONSTRAINT `order_contentsfk1` FOREIGN KEY (`Order_ID`) REFERENCES `ORDERS` (`Order_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `CUSTOMERS` (
`Mobile_Number` varchar(10) NOT NULL,
`Name` varchar(45) NOT NULL,
`Age` int(3) DEFAULT NULL,
`Gender` enum('M','F') DEFAULT NULL,
`Email` varchar(100) DEFAULT NULL,
PRIMARY KEY (`Mobile_Number`),
UNIQUE KEY `Mobile_Number_UNIQUE` (`Mobile_Number`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `ORDERS` (
`Order_ID` int(10) NOT NULL AUTO_INCREMENT,
`Mobile_Number` varchar(10) NOT NULL,
`Postcode` int(4) NOT NULL,
`Timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`Order_ID`),
KEY `ordersfk1_idx` (`Mobile_Number`),
KEY `ordersfk2_idx` (`Postcode`),
CONSTRAINT `ordersfk1` FOREIGN KEY (`Mobile_Number`) REFERENCES `CUSTOMERS` (`Mobile_Number`) ON DELETE NO ACTION ON UPDATE CASCADE,
CONSTRAINT `ordersfk2` FOREIGN KEY (`Postcode`) REFERENCES `STORES` (`Postcode`) ON DELETE NO ACTION ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
CREATE TABLE `STORES` (
`Postcode` int(4) NOT NULL DEFAULT '0',
`Address` varchar(100) DEFAULT NULL,
`Phone_Number` varchar(10) DEFAULT NULL,
PRIMARY KEY (`Postcode`),
UNIQUE KEY `Postcode_UNIQUE` (`Postcode`),
UNIQUE KEY `Address_UNIQUE` (`Address`),
UNIQUE KEY `Phone_Number_UNIQUE` (`Phone_Number`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I need to find the following:
Problem Statement
For each customer, list the store details of their favorite pizza
store, where a store is the favorite if it is the one where the
customer purchased the most pizzas).
I have managed to figure it out upto the following query:
select `Name`,SUM(quantity) as hqty,COUNT(*),Postcode from CUSTOMERS natural join orders natural join order_contents group by Mobile_Number,postcode;
This gives me a result as the following:
+---------------+------+----------+----------+
| Name | hqty | COUNT(*) | Postcode |
+---------------+------+----------+----------+
| Homer Simpson | 19 | 3 | 4000 |
| Homer Simpson | 1 | 1 | 4502 |
| Ned Flanders | 2 | 1 | 4000 |
+---------------+------+----------+----------+
But in this case there are two instances of the same customer ( i.e. Homer Simpson). Why is this so? I figured that I would need to use a combination of aggregate function.
Any help/explanation would be great.
Cheers!
[UPDATE 1]
Just for reference:
select * from CUSTOMERS natural join orders natural join
order_contents;
The above query produces this:
+----------+---------------+---------------+------+--------+-----------------+----------+---------------------+--------------+----------+
| Order_ID | Mobile_Number | Name | Age | Gender | Email | Postcode | Timestamp | Pizza_Name | Quantity |
+----------+---------------+---------------+------+--------+-----------------+----------+---------------------+--------------+----------+
| 1 | 0412345678 | Homer Simpson | 38 | M | homer#doh.com | 4000 | 2014-08-21 19:38:01 | Garlic Bread | 9 |
| 1 | 0412345678 | Homer Simpson | 38 | M | homer#doh.com | 4000 | 2014-08-21 19:38:01 | Hawaiian | 9 |
| 2 | 0412345678 | Homer Simpson | 38 | M | homer#doh.com | 4000 | 2014-08-21 19:38:01 | Vegan Lovers | 1 |
| 3 | 0412345678 | Homer Simpson | 38 | M | homer#doh.com | 4502 | 2014-08-21 19:38:12 | Meat Lovers | 1 |
| 4 | 0412345679 | Ned Flanders | 60 | M | ned#vatican.net | 4000 | 2014-08-21 19:39:09 | Meat Lovers | 2 |
+----------+---------------+---------------+------+--------+-----------------+----------+---------------------+--------------+----------+
Also please note the problem statement
SELECT *
FROM customers c
JOIN stores s
ON s.postcode =
(
SELECT postcode
FROM orders o
JOIN order_contents oc
USING (order_id)
WHERE o.mobile_number = c.mobile_number
GROUP BY
postcode
ORDER BY
SUM(quantity) DESC
LIMIT 1
)
This won't show customers who have made no orders at all. If you need those, change the JOIN to stores to a LEFT JOIN
Group by your customers primary key (maybe an ID).
The reason you are getting duplicate customers is because you are grouping the query by mobile_number and postcode, which isn't making a unique index.
Your query should become something like this:
select Name ,SUM(quantity) as hqty,COUNT(*),Postcode from CUSTOMERS natural join orders natural join order_contents group by CUSTOMERS.id
Replace ID with whatever the customers table PK is and it should group by the customer uniquely.
I have found that MySQL (Win 7 64, 5.6.14) does not use index properly if I specify table output for IN statement. USER table contains 900k records.
If I use IN (_SOME_TABLE_OUTPUT_) syntax - I get fullscan for all 900k users. Query runs forever.
If I use IN ('CONCRETE','VALUES') syntax - I get a correct index usage.
How can I make MySQL finally USE the index?
1st case:
explain SELECT gu.id FROM USER gu WHERE gu.uuid in
(select '11b6a540-0dc5-44e0-877d-b3b83f331231' union
select '11b6a540-0dc5-44e0-877d-b3b83f331232');
+----+--------------------+------------+-------+---------------+------+---------+------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+-------+---------------+------+---------+------+--------+--------------------------+
| 1 | PRIMARY | gu | index | NULL | uuid | 257 | NULL | 829930 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 3 | DEPENDENT UNION | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------------+------------+-------+---------------+------+---------+------+--------+--------------------------+
2nd case:
explain SELECT gu.id FROM USER gu WHERE gu.uuid in
('11b6a540-0dc5-44e0-877d-b3b83f331231');
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| 1 | SIMPLE | gu | ref | uuid | uuid | 257 | const | 1 | Using where; Using index |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
Table structure:
CREATE TABLE `USER` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`email` varchar(255) DEFAULT NULL,
`uuid` varchar(255) NOT NULL,
`partner_id` bigint(20) NOT NULL,
`password` varchar(255) DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique-email` (`partner_id`,`email`),
KEY `uuid` (`uuid`),
CONSTRAINT `fk_USER_partner` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`) ON DELETE CASCADE,
CONSTRAINT `FKB2D9FEBE725C505E` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3315452 DEFAULT CHARSET=latin1
FORCE INDEX and USE INDEX statements don't change anything.
Demonstration SQLfiddle: http://sqlfiddle.com/#!2/c607e1/2
In fact I faced such problem before and it happened that I had one table that had a single column set as UTF-8 and the other tables where latin1. It did not matter what I did, MySQL insisted on using no indexes. The problem is quite well described on this blog post Slow queries in MySQL due to collation problems. Once you manage to fix the character set, I believe any of the queries will work.
An inner join on your virtual table might give you better performance. Try something along these lines.
SELECT gu.id
FROM USER gu
INNER JOIN (
select '11b6a540-0dc5-44e0-877d-b3b83f331231' uuid
union all
select '11b6a540-0dc5-44e0-877d-b3b83f331232') ids
on gu.uuid = ids.uuid;
So, here's basically the problem:
For starter, I am not asking anyone to do my homework, but to just give me a nudge in the right direction.
I have 2 tables containing names and contact data for practicing
Let's call these tables people and contact.
Create Table for people:
CREATE TABLE `people` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fname` tinytext,
`mname` tinytext,
`lname` tinytext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Create Table for contact:
CREATE TABLE `contact` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`person_id` int(10) unsigned NOT NULL DEFAULT '0',
`tel_home` tinytext,
`tel_work` tinytext,
`tel_mob` tinytext,
`email` text,
PRIMARY KEY (`id`,`person_id`),
KEY `fk_contact` (`person_id`),
CONSTRAINT `fk_contact` FOREIGN KEY (`person_id`) REFERENCES `people` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
When getting the contact information for each person, the query I use is as follows:
SELECT p.id, CONCAT_WS(' ',p.fname,p.mname,p.lname) name, c.tel_home, c.tel_work, c.tel_mob, c.email;
This solely creates a response like:
+----+----------+---------------------+----------+---------+---------------------+
| id | name | tel_home | tel_work | tel_mob | email |
+----+----------+---------------------+----------+---------+---------------------+
| 1 | Jane Doe | 1500 (xxx-xxx 1500) | NULL | NULL | janedoe#example.com |
| 2 | John Doe | 1502 (xxx-xxx 1502) | NULL | NULL | NULL |
| 2 | John Doe | NULL | NULL | NULL | johndoe#example.com |
+----+----------+---------------------+----------+---------+---------------------+
The problem with this view is that row 1 and 2 (counting from 0) could've been grouped to a single row.
Even though this "non-pretty" result is due to corrupt data, it is likely that this will occur in a multi-node database environment.
The targeted result would be something like
+----+----------+---------------------+----------+---------+---------------------+
| id | name | tel_home | tel_work | tel_mob | email |
+----+----------+---------------------+----------+---------+---------------------+
| 1 | Jane Doe | 1500 (xxx-xxx 1500) | NULL | NULL | janedoe#example.com |
| 2 | John Doe | 1502 (xxx-xxx 1502) | NULL | NULL | johndoe#example.com |
+----+----------+---------------------+----------+---------+---------------------+
Where the rows with the same id and name are grouped when still showing the effective data.
Side notes:
innodb_version: 5.5.32
version: 5.5.32-0ubuntu-.12.04.1-log
version_compile_os: debian_linux-gnu
You could use GROUP_CONCAT(), which "returns a string result with the concatenated non-NULL values from a group":
SELECT p.id,
GROUP_CONCAT(CONCAT_WS(' ',p.fname,p.mname,p.lname)) name,
GROUP_CONCAT(c.tel_home) tel_home,
GROUP_CONCAT(c.tel_work) tel_work,
GROUP_CONCAT(c.tel_mob ) tel_mob,
GROUP_CONCAT(c.email ) email
FROM my_table
GROUP BY p.id