2010-07-27 3 views
1

Je vais avoir le problème suivant avec 2 tables MySQL qui ont une relation: Je peux facilement interroger le tableau 1 (adresse) quand je veux une liste complète ou filtrer le résultat par nom ou par e-mail ou tel . Mais maintenant je dois interroger la table 1 et la filtrer en fonction du contenu relationnel de la table 2 (intérêts). Alors, je dois trouver une ligne (généralement plusieurs lignes) dans le tableau 1 que si une des conditions (ou plus) sont réunies dans le tableau 2.requête de filtre MySQL par rapport

Voici les tableaux:

CREATE TABLE IF NOT EXISTS `address` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
    `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
    `countryCode` char(2) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `languageCode` char(2) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `emailUnique` (`email`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

INSERT INTO `address` (`id`, `name`, `email`, `countryCode`, `languageCode`, `timestamp`) VALUES 
(1, '', '[email protected]', 'BE', 'nl', '2010-07-16 14:07:00'), 
(2, '', '[email protected]', 'BE', 'fr', '2010-07-16 14:10:25'); 

CREATE TABLE IF NOT EXISTS `interests` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `address_id` int(11) unsigned NOT NULL, 
    `cat` char(2) COLLATE utf8_unicode_ci NOT NULL, 
    `subcat` char(2) COLLATE utf8_unicode_ci NOT NULL, 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `address_id` (`address_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

INSERT INTO `interests` (`id`, `address_id`, `cat`, `subcat`, `timestamp`) VALUES 
(1, 1, 'aa', 'xx', '2010-07-16 14:07:00'), 
(2, 1, 'aa', 'yy', '2010-07-16 14:07:00'), 
(3, 2, 'aa', 'xx', '2010-07-16 14:07:00'), 
(4, 2, 'bb', 'zz', '2010-07-16 14:07:00') 
(5, 2, 'aa', 'yy', '2010-07-16 14:07:00'); 

ALTER TABLE `interests` 
    ADD CONSTRAINT `interests_ibfk_1` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION; 

Par exemple, je besoin de trouver l'adresse (s) qui a (ont) comme intérêt cat = aa et subcat = xx. Ou, un autre exemple, j'ai besoin de l'adresse (s) avec comme intérêt à la fois cat = aa et subcat = xx ET cat = aa et subcat = aa. Spécialement, ce dernier est important et il faut garder à l'esprit que les tables d'adresses et d'intérêts seront de longues listes et que le nombre de combinaisons chat/subcat variera. Je travaille avec des requêtes de référence par Zend_Db_Table (findDependentRowset) au moment, mais cette solution est une façon de ralentir pour les listes d'adresses de numérotation 100s et même 1000s de hits.

Nous vous remercions de votre aide.

Répondre

1

j'ai ajouté une autre ligne dans votre table d'intérêts, de démontrer un autre jeu de résultats entre les deux exemples:

INSERT INTO interests VALUES (6, 2, 'aa', 'vv', '2010-07-16 14:07:00'); 

Ensuite, vous pouvez essayer d'utiliser les sous-requêtes corrélées comme suit:

SELECT * 
FROM address a 
WHERE EXISTS (SELECT id 
       FROM interests 
       WHERE address_id = a.id AND 
         (cat = 'aa' and subcat = 'xx')); 

Résultat:

+----+------+--------------------+-------------+--------------+---------------------+ 
| id | name | email    | countryCode | languageCode | timestamp   | 
+----+------+--------------------+-------------+--------------+---------------------+ 
| 1 |  | [email protected]  | BE   | nl   | 2010-07-16 14:07:00 | 
| 2 |  | [email protected] | BE   | fr   | 2010-07-16 14:10:25 | 
+----+------+--------------------+-------------+--------------+---------------------+ 
2 rows in set (0.00 sec) 

Pour le deuxième exemple, nous testons pour la nouvelle ligne ajoutée précédemment afin de ne pas avoir le même résultat que ci-dessus:

SELECT * 
FROM address a 
WHERE EXISTS (SELECT id 
       FROM interests 
       WHERE address_id = a.id AND 
         (cat = 'aa' and subcat = 'xx')) AND 
     EXISTS (SELECT id 
       FROM interests 
       WHERE address_id = a.id AND 
         (cat = 'aa' and subcat = 'vv')); 

Résultat:

+----+------+--------------------+-------------+--------------+---------------------+ 
| id | name | email    | countryCode | languageCode | timestamp   | 
+----+------+--------------------+-------------+--------------+---------------------+ 
| 2 |  | [email protected] | BE   | fr   | 2010-07-16 14:10:25 | 
+----+------+--------------------+-------------+--------------+---------------------+ 
1 row in set (0.00 sec) 

En utilisant les sous-requêtes est facile et corrélées simple. Cependant, gardez à l'esprit que ce n'est peut-être pas le meilleur en termes de performances, car les sous-requêtes corrélées seront exécutées une fois pour chaque adresse de la requête externe.

+0

Vive votre réponse élaborée. D'une certaine manière, c'est ce que j'ai fait avec Zend. Pour chaque adresse, vérifiez si la condition est remplie par le findDependentRowset. Mais les tables sont trop grandes pour cela, ou mieux dit, le total des requêtes prend trop de temps. – Peter

+0

Correction, ceci est remarquablement plus rapide que findDependentRowset. J'ai effectué quelques tests, à la fois avec des constructions AND et OU et ils montrent une performance assez pratique, au moins sur mon DB de développement actuel. Je vais à une réunion maintenant, mais je vais tester cela plus tard. Cela pourrait très bien être la solution pour moi. – Peter

2
SELECT a.name FROM address a 
INNER JOIN interests i ON (a.id = i.address_id) 
WHERE i.cat = "aa" AND i.subcat IN ('xx', 'yy') 
+0

nette et rapide, merci! Si je vois bien, toutes les adresses qui ont le aa/xx ou le combo aa/yy apparaîtront. Mais que faire si je veux ceux avec aa/xx et aa/yy? Comment aller de jeter un chat dans le mélange? Serait-ce la bonne façon: SELECT a.name adresse FROM un intérêt INNER JOIN i ON (a.id = i.address_id) OU (i.cat = "aa" ET i.subcat IN ('xx', 'yy')) OU (i.cat = "bb" ET i.subcat IN ('zz', 'ww')) – Peter