Подсчет левого соединения в зависимости от другого левого соединения - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть этот запрос:

SELECT options.id, options.text, 
COUNT(options2.id) AS num_children
FROM options
JOIN history_uids AS uids
    ON uids.uid = options.id
LEFT JOIN options AS options2
    ON (options.id = options2.id_parent)
LEFT JOIN history_uids AS uids1
    ON uids1.uid = options2.id
WHERE (
options.id = 25
AND (uids1.active = 1 OR
options2.id IS NULL) # Problem
)
GROUP BY `options`.`id`

Существует таблица options, а другая, history_uids, которая имеет столбец с именем uid с идентификатором всех параметров и *Столбец 1007 * установлен в 1 или 0.

Я ожидаю получить результат с:

  1. Идентификатор и текст опции, которая имеет id 25, идля которого active установлено значение 1 в history_uids.
  2. Количество опций, для которых id_parent равно id (25) и для которых установлено active в history_uids1

Так что, каково бы ни было это число, я должен получить свою строку, если для active установлено значение 1. Я не могу понять, как этого добиться: я хочу установить в качестве последнего условия uids1.active = 1 OR "options2 doesn't exist", ночтобы получить это, у меня должно быть условие active в ON из options2, что невозможно, потому что в этот момент на таблицу history_uids еще не ссылаются ...

В моем случаев строке active установлено значение 1 и 5 дочерних элементов, для active установлено значение 0, поэтому я должен получить строку со значением num_children, установленным в 0. Вместо любой комбинации, которую я делаю в JOINили WHERE Я получаю либо num_children, установленный на 5, либо никакого результата вообще.

Спасибо за вашу помощь (и за чтение!)

Вот полная структура и данные длятестирование:

CREATE TABLE `history_uids` (
  `uid` int(10) NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `history_uids` (`uid`, `active`) VALUES
(1, 1),
(2, 0),
(3, 0),
(4, 0),
(5, 0),
(6, 0);
CREATE TABLE `options` (
  `id` int(10) NOT NULL,
  `id_parent` int(10) DEFAULT NULL,
  `text` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `options` (`id`, `id_parent`, `text`) VALUES
(1, NULL, 'parent active'),
(2, 1, 'child 1 inactive'),
(3, 1, 'child 2 inactive'),
(4, 1, 'child 3 inactive'),
(5, 1, 'child 4 inactive'),
(6, 1, 'child 5 inactive');
ALTER TABLE `history_uids`
  ADD PRIMARY KEY (`uid`);
ALTER TABLE `options`
  ADD PRIMARY KEY (`id`),
  ADD KEY `id_parent` (`id_parent`);
ALTER TABLE `options`
  ADD CONSTRAINT `ibfk_3` FOREIGN KEY (`id_parent`) REFERENCES `options`     (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `ibfk_4` FOREIGN KEY (`id`) REFERENCES `history_uids` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE;

1 Ответ

0 голосов
/ 22 ноября 2018

Необходимо поместить тест active для дочерней строки в предложение ON, чтобы неактивные строки были отфильтрованы из LEFT JOIN.И вы должны считать uids1.uid, а не options2.id, поскольку неактивные строки не отфильтровываются, пока вы не присоединитесь к uids1.

SELECT options.id, options.text, 
    COUNT(uids1.uid) AS num_children
FROM options
JOIN history_uids AS uids
    ON uids.uid = options.id
LEFT JOIN options AS options2
    ON (options.id = options2.id_parent)
LEFT JOIN history_uids AS uids1
    ON uids1.uid = options2.id and uids1.active = 1
WHERE 
uids.active = 1
GROUP BY `options`.`id`

DEMO

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...