I'm trying hard as I can to transform my query to get rid of subqueries. I know its better to not use subqueries, but my first reason to change this query is because my ORM (Doctrine) isn't able to use any join with subquery, it doesn't support it (or CTEs).
Is there a way to get rid of subqueries in this query?
SELECT
s.id,
e.exception,
s.name,
w.url,
w.web_id,
w.active,
w.suspended,
r.email,
p.name AS partner,
p.id AS partnerId,
contacts.names AS contactNames,
contacts.tels AS contactTels,
contacts.emails AS contactEmails
FROM
service s
JOIN
web w ON s.web_id = w.id
JOIN
rus r ON w.rus_id = r.id
JOIN
partner p ON r.partner_id = p.id
LEFT JOIN
exception e ON e.service_id = s.id
LEFT JOIN
(SELECT
p.id,
GROUP_CONCAT(c.name) names,
GROUP_CONCAT(c.tel) tels,
GROUP_CONCAT(c.email) emails
FROM
partner p
LEFT JOIN contact c ON c.partner_id = p.id
WHERE
c.main = 1 OR c.important = 1
GROUP BY p.id) contacts ON contacts.id = p.id
LEFT JOIN
contact c ON c.partner_id = p.id
Tables and sample data:
CREATE TABLE `partner` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`ico` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`created` datetime NOT NULL,
`active` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `partner_idx_active` (`active`),
FULLTEXT KEY `partnerEntity` (`name`,`ico`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `partner` (`id`, `name`, `ico`, `created`, `active`) VALUES
(1, 'partner1', '123', '2021-05-18 22:27:24', 1);
CREATE TABLE `contact` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`partner_id` int(11) DEFAULT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`tel` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`created` datetime NOT NULL,
`active` int(11) NOT NULL,
`main` int(11) DEFAULT NULL,
`important` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_4C62E6389393F8FE` (`partner_id`),
FULLTEXT KEY `contactEntity` (`name`,`email`,`tel`),
CONSTRAINT `FK_4C62E6389393F8FE` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `contact` (`id`, `partner_id`, `name`, `email`, `tel`, `created`, `active`, `main`, `important`) VALUES
(1, 1, 'contact1', 'test@test.com', '123456789', '2021-05-18 22:28:30', 1, 1, NULL),
(2, 1, 'contact2', 'test2@test.com', '123456788', '2021-05-18 22:28:48', 1, NULL, 1),
(3, 1, 'contact3', 'test3@test.com', '123451234', '2021-05-18 22:29:13', 1, NULL, NULL);
CREATE TABLE `rus` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`partner_id` int(11) DEFAULT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`active` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_3370C8199393F8FE` (`partner_id`),
KEY `rus_idx_active` (`active`),
FULLTEXT KEY `rusEntity` (`email`),
CONSTRAINT `FK_3370C8199393F8FE` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `rus` (`id`, `partner_id`, `email`, `created`, `active`) VALUES
(1, 1, 'test@test.com', '2021-05-18 22:27:36', 1);
CREATE TABLE `service` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`web_id` int(11) DEFAULT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`active` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_E19D9AD2FE18474D` (`web_id`),
KEY `service_idx_active` (`active`),
FULLTEXT KEY `serviceEntity` (`name`),
CONSTRAINT `FK_E19D9AD2FE18474D` FOREIGN KEY (`web_id`) REFERENCES `web` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `service` (`id`, `web_id`, `name`, `created`, `active`) VALUES
(1, 1, 'service1', '2021-05-18 22:28:08', 1);
CREATE TABLE `exception` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`partner_id` int(11) DEFAULT NULL,
`exception` longtext COLLATE utf8_unicode_ci NOT NULL,
`created` datetime DEFAULT NULL,
`service_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK_7FC98E6D9393F8FE` (`partner_id`),
KEY `FK_7FC98E6DED5CA9E6` (`service_id`),
CONSTRAINT `FK_7FC98E6D9393F8FE` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`),
CONSTRAINT `FK_7FC98E6DED5CA9E6` FOREIGN KEY (`service_id`) REFERENCES `service` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `exception` (`id`, `partner_id`, `exception`, `created`, `service_id`) VALUES
(1, 1, 'test..', '2021-05-18 22:31:14', 1);
CREATE TABLE `web` (
`suspended` int(11) NOT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`rus_id` int(11) DEFAULT NULL,
`url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`web_id` int(5) unsigned zerofill DEFAULT NULL,
`created` datetime NOT NULL,
`active` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_15C9385126907186` (`rus_id`),
KEY `web_idx_active` (`active`),
FULLTEXT KEY `webEntity` (`url`),
CONSTRAINT `FK_15C9385126907186` FOREIGN KEY (`rus_id`) REFERENCES `rus` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `web` (`suspended`, `id`, `rus_id`, `url`, `web_id`, `created`, `active`) VALUES
(0, 1, 1, 'www.test.com', 01337, '2021-05-18 22:27:54', 1);
Best Answer
You can just place all the other columns in the
GROUP BY
. It's more verbose, but it does the job.SELECT
into theGROUP BY
also. Although MariaDB and MySQL allow other columns in theSELECT
, it is effectively anANY(...)
aggregate, and is not deterministic in many cases.contact
in theON
clause now, do not filter in theWHERE
partner
andcontact
lookups, they seems to serve no purpose.