2012-04-02 4 views
2

Ich habe eine Reihe von Ressourcen auf SO und im Web gesucht, um herauszufinden, warum meine MySQL Select-Anweisung nicht die richtigen Zeilen/Ergebnisse zurückgibt . Ich entschuldige mich im Voraus, wenn es hier eine Antwort gibt, die ich verpasst habe und es wertschätzt, dass jemand mich darauf hinweist.SELECT-Anweisung, die Werte über mehrere Tabellen hinweg vergleicht nicht die richtigen Zeilen

Ein kleiner Hintergrund. Angenommen, eine E-Mail-Kampagnenanwendung enthält die folgenden Tabellen: Benutzer, Gruppen, Kampagnen, Warteschlange, Managergruppen und Einstellungen. Jede Gruppe hat ihre eigenen Einstellungen mit einem Flag namens 'delivery_enabled' - 1 oder 0. Eine wichtige Anmerkung ist, wenn eine Gruppe von einer anderen Gruppe verwaltet wird, verwendet die 'managee' Gruppe automatisch die Einstellungen der Verwaltungsgruppe. Selbst wenn die Einstellungen der Gruppe 'managee' auf '1' gesetzt sind und ihre Verwaltungsgruppe auf '0' gesetzt ist, werden diese ebenfalls als 0 behandelt. Ich hoffe, ich habe das klar erklärt:/

Die folgende Anweisung wird verwendet Zeilen aus der Tabelle "Warteschlange" zurückgeben - die Warteschlange enthält die Nachrichten/E-Mails, die von der Anwendung noch nicht übermittelt wurden. Die Anweisung überprüft, ob die Gruppe des Benutzers settings.delivery_enabled = 1 ist - unter Berücksichtigung (über CASE), ob wir die eigenen Gruppeneinstellungen des Benutzers oder die Einstellungen seiner Verwaltungsgruppe verwenden sollen.

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 

Die Ergebnisse, die ich zeigen immer, dass eine Gruppe, die eine Verwaltung Gruppe noch ihre eigenen Einstellungen verwendet hat und nicht die Verwaltungsgruppe. Ich habe das Gefühl, dass etwas mit meiner CASE-Anweisung in der WHERE CLAUSE nicht stimmt, wodurch die Abfrage auf die ELSE zurückfällt.

Wenn jemand es ausprobieren möchte, hier sind die Daten, die ich dafür verwende.

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'); 

Noch eine Anmerkung ist, dass ich eine skalierte zurück Version mit nur drei Tischen versuchen haben und weit weniger Daten, die in Ordnung schien zu funktionieren, aber einmal habe ich die gleiche Methode in dem größeren Szenario (die mehrere Tabellen hat Hinweis gegen) es hat nicht funktioniert.

Wenn weitere Informationen benötigt werden, lassen Sie es mich wissen.

Antwort

0

Eine schnellere und einfacher zu verstehende Methode wäre, einfach weiterzumachen und links die beiden Einstellungstabellen zu verbinden und dann den Managereinstellungen zu erlauben, die einzelnen Einstellungen durch die Verwendung von Coalesce() zu überschreiben.

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 
+0

ich den Code gegen den Tabellen nicht getestet haben, lassen Sie mich so, wenn Sie Fehler zu sehen. Beachten Sie auch, dass ich Ihren Managern beitreten und 2 Einstellungen vornehmen kann. Es besteht die Möglichkeit, dass delivery_enabled null ist, wenn keine Benutzereinstellungen oder Verwaltungsgruppeneinstellungen vorhanden sind. – Jordan

+0

Toller Ansatz dafür! Wenn ich die Abfrage für den Datensatz ausführen (ich habe den umgekehrten Schrägstrich nach der ersten inneren Join-Zeile entfernt, weil ein Fehler verursacht wurde), habe ich eine "Unbekannte Spalte" queue.user_id 'in' on clause '". Ich habe den zweiten inneren Join auf "Inner Join users On campaigns.user_id = users.id" geändert und ausgeführt. Die Ergebnisse geben den Einstellungen einer Verwaltungsgruppe keine Priorität. Die Ergebnisse zeigen die Einstellung für die eigene Gruppe unabhängig davon, ob sie von einer anderen Gruppe verwaltet werden oder nicht. Ich hoffe, ich habe Sinn gemacht. – Derek

+0

Das bedeutet, dass die linke äußere Verknüpfung von managers_groups keine Zeilen auswählt. Ist es möglich, dass es keine Daten gibt, bei denen die managee_group_id gleich der group_id eines Benutzers ist? Vielleicht habe ich die falschen Spalten für diesen Join verwendet? – Jordan

0

aus Ihrer CASE-Anweisung in der WHERE-Klausel:

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

'has_manager' ist ein String-Literal. Wenn Sie sie auswählen, wird immer das Zeichenfolgenliteral 'has_manager' ausgegeben. So nimmt Ihre CASE-Anweisung immer nur die erste Verzweigung.

Vielleicht bedeutete Sie CASE (SELECT has_manager ...) WHEN 1 THEN ...

+0

Guter Fang, Hammerite. Ich habe diese Änderung gemacht und auch '(SELECT has_manager ...' zu '(SELECT 1 ...') geändert, da ich einen unbekannten Spaltenfehler erhielt. Das Ausführen der neuen Abfrage führt immer noch zu falschen Ergebnissen. Mit meinem Datensatz bekomme ich 17 Zeilen wurden zurückgegeben, wenn es nur 4 sein sollte. Wenn ich 't5.delivery_enabled = 1' in 't5.delivery_enabled = 0' ändere, bekomme ich alle 19 Zeilen aus der Warteschlange, obwohl ich nur 15 bekommen sollte. Seltsam bereinigen so wie es sein könnte, es sieht immer noch so aus, als ob es funktionieren sollte. – Derek

Verwandte Themen