Оператор SELECT, который сравнивает значения в нескольких таблицах, не возвращает правильные строки - PullRequest
2 голосов
/ 02 апреля 2012

Я искал несколько ресурсов в SO и в Интернете, чтобы попытаться выяснить, почему мой оператор выбора MySQL не возвращает правильные строки / результаты. Я заранее прошу прощения, если есть ответ, который я пропустил, и ценю, что кто-то указал мне.

Немного фона. Предположим, что приложение для кампании по электронной почте содержит таблицы: пользователи, группы, кампании, очередь, manager_groups и настройки. Каждая группа имеет свои собственные настройки, которые имеют флаг под названием «delivery_enabled» - 1 или 0. Важное замечание: когда группа управляется другой группой, группа «Управляющий» автоматически будет использовать настройки управляющей группы. Таким образом, даже если для настроек группы «managee» для delivery_enabled установлено значение 1, а для их группы управления установлено значение 0, их значения также будут рассматриваться как 0. Надеюсь, я четко объяснил это: /

Следующий оператор используется для возврата строк из таблицы 'queue' - в очереди хранятся сообщения / электронные письма, ожидающие доставки приложением. Оператор проверяет, имеет ли группа пользователей settings.delivery_enabled = 1 - принимая во внимание (через CASE), должны ли мы использовать настройки собственной группы пользователя или настройки их управляющей группы.

SELECT 
t1.*
FROM 
queue t1, 
campaigns t2, 
users t3,
managers_groups t4, 
settings t5  
WHERE
( t1.campaign_status = 3 && t1.campaign_id = t2.id && t2.user_id = t3.id && t5.delivery_enabled = 1 ) && 
CASE ( SELECT 1 FROM managers_groups WHERE managee_group_id = t3.group_id )
 WHEN 1 THEN t4.manager_group_id = t5.group_id 
 ELSE t3.group_id = t5.group_id
END
GROUP BY t1.id 
ORDER BY t1.send_at ASC, t1.id ASC

Результаты, которые я получаю, показывают, что группа, в которой есть управляющая группа, по-прежнему использует свои собственные настройки, а не управляющую группу. Я чувствую, что что-то не так с моим оператором CASE в WHERE CLAUSE, что вызывает откат запроса на ELSE.

Если кто-то хочет попробовать, вот данные, которые я использую для этого.

CREATE TABLE IF NOT EXISTS `campaigns` (
  `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(12) NOT NULL,
  `name` varchar(150) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=17 ;

--
-- Dumping data for table `campaigns`
--

INSERT INTO `campaigns` (`id`, `user_id`, `name`) VALUES
(16, 72, 'Steve''s Campaign'),
(13, 83, 'Kelly''s Campaign'),
(14, 77, 'Narek''s Campaign'),
(15, 75, 'Cynthia''s Campaign');

-- --------------------------------------------------------

--
-- Table structure for table `groups`
--

CREATE TABLE IF NOT EXISTS `groups` (
  `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(150) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=110 ;

--
-- Dumping data for table `groups`
--

INSERT INTO `groups` (`id`, `name`) VALUES
(108, 'Managers 002'),
(107, 'Managers 001'),
(106, 'Members 001 - Group B'),
(104, 'Members 002 - Group A'),
(103, 'Members 001 - Group A');

-- --------------------------------------------------------

--
-- Table structure for table `managers_groups`
--

CREATE TABLE IF NOT EXISTS `managers_groups` (
  `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
  `manager_group_id` int(12) NOT NULL,
  `managee_group_id` int(12) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=280 ;

--
-- Dumping data for table `managers_groups`
--

INSERT INTO `managers_groups` (`id`, `manager_group_id`, `managee_group_id`) VALUES
(274, 108, 104),
(279, 107, 103);

-- --------------------------------------------------------

--
-- Table structure for table `queue`
--

CREATE TABLE IF NOT EXISTS `queue` (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `campaign_id` int(12) NOT NULL,
  `campaign_status` int(2) NOT NULL DEFAULT '0',
  `send_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=20 ;

--
-- Dumping data for table `queue`
--

INSERT INTO `queue` (`id`, `campaign_id`, `campaign_status`, `send_at`) VALUES
(1, 16, 3, '2012-04-01 20:05:45'),
(2, 16, 3, '2012-04-01 20:05:45'),
(3, 16, 3, '2012-04-01 20:05:45'),
(4, 16, 3, '2012-04-01 20:05:45'),
(5, 15, 3, '2012-04-01 20:00:18'),
(6, 15, 3, '2012-04-01 20:00:18'),
(7, 15, 3, '2012-04-01 20:00:18'),
(8, 15, 3, '2012-04-01 20:00:18'),
(9, 15, 3, '2012-04-01 20:00:18'),
(10, 15, 3, '2012-04-01 20:00:18'),
(11, 15, 3, '2012-04-01 20:00:18'),
(12, 14, 3, '2012-04-01 20:00:06'),
(13, 14, 3, '2012-04-01 20:00:06'),
(14, 14, 3, '2012-04-01 20:00:06'),
(15, 14, 3, '2012-04-01 20:00:06'),
(16, 14, 3, '2012-04-01 20:00:06'),
(17, 14, 3, '2012-04-01 20:00:06'),
(18, 13, 3, '2012-04-01 19:59:53'),
(19, 13, 3, '2012-04-01 19:59:53');

-- --------------------------------------------------------

--
-- Table structure for table `settings`
--

CREATE TABLE IF NOT EXISTS `settings` (
  `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
  `group_id` int(12) unsigned NOT NULL,
  `delivery_enabled` int(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=22 ;

--
-- Dumping data for table `settings`
--

INSERT INTO `settings` (`id`, `group_id`, `delivery_enabled`) VALUES
(19, 107, 1),
(20, 108, 0),
(18, 106, 0),
(16, 104, 1),
(15, 103, 1);

-- --------------------------------------------------------

--
-- Table structure for table `users`
--

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(12) unsigned NOT NULL AUTO_INCREMENT,
  `group_id` int(12) NOT NULL,
  `username` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=86 ;

--
-- Dumping data for table `users`
--

INSERT INTO `users` (`id`, `group_id`, `username`) VALUES
(83, 106, 'kelly'),
(77, 104, 'narek'),
(75, 104, 'cynthia'),
(72, 103, 'steve');

Еще одно замечание: я попробовал сокращенную версию с тремя таблицами и гораздо меньшим количеством данных, которая, как мне показалось, работала нормально, но однажды я использовал ту же методологию в более широком сценарии (в котором есть больше таблиц, на которые можно ссылаться) не работал.

Если потребуется дополнительная информация, дайте мне знать.

Ответы [ 2 ]

0 голосов
/ 02 апреля 2012

В вашем операторе CASE в предложении WHERE:

SELECT 'has_manager' FROM managers_groups WHERE managee_group_id = t3.group_id )
 WHEN 'has_manager'

'has_manager' - строковый литерал.При его выборе всегда получается строковый литерал 'has_manager'.Таким образом, ваш оператор CASE принимает только первую ветвь.

Возможно, вы имели в виду CASE (SELECT has_manager ...) WHEN 1 THEN ...

0 голосов
/ 02 апреля 2012

Более быстрый и легкий для понимания способ справиться с этим - просто присоединиться к обеим таблицам настроек и затем разрешить настройкам менеджера переопределять отдельные настройки с помощью Coalesce ().

Select
    queue.*,
    Coalesce(manager_group_settings.delivery_enabled, user_settings.delivery_enabled) As setting_delivery_enabled
From queue
Inner Join campaigns On queue.campaign_id = campaigns.id
Inner Join users On queue.user_id = users.id
Left Outer Join managers_groups On managers_groups.managee_group_id = users.group_id
Left Outer Join settings As user_settings On user_settings.group_id = users.group_id
Left Outer Join settings As manager_group_settings On manager_group_settings.group_id = managers_groups.managee_group_id
Group By queue.id
Order By queue.send_at, queue.id
...