Probleme syntaxe pour intersection
Voilà le problème :
Soit une table avec des id_user et des id_lieu
id_user | id_lieu
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
4 | 1
4 | 3
Je veut tout les Id_user qui fréquente a la fois les Id_lieu '1' et '2'
Je me doute qu'il faut faire un intersection chose que je sais faire en SQL avec INTERSECT mais malheureusement c'est pas dispo en MySQL donc je me suis rabattu sur une syntaxe avec IN mais impossible de trouvé la bonne syntaxe.
Une idée ?
Autre solution, plus rapide avec des listes importantes
La solution proposée marche bien, mais sa réalisation peut prendre des plombes .
Mettons que tu aies 2 listes de personnes: list_A and list_B. Tu veux savoir quelles sont les personnes qui sont dans A et pas dans B. D'un point de vue ensembliste, tu cherches à faire "A moins B".
Solution facile, mais qui prend du temps:
select person from list_A where person not in (select person from list_B);
Dans mon cas, 2 listes de quelques milliers de lignes suffisent à mettre mon serveur 1GB à genoux pendant qqes minutes.
Le temps de calcul est divisé par 1000 en utilisant l'algorithme suivant:
1/ crée une table temporaire où tu dumpes les 2 listes
2/ utilise les fonctions "group" de mysql pour séparer les éléments de l'intersection des éléments hors-intersection
Exemple:
Code:
1 2 3 4
|
create temporary table dump (person varchar(30), list_source char); /* crée la table temporaire*/
insert into dump select person, 'A' from list_A; /* dump les éléments de list_A dans la table et marque les par la lettre "A"*/
insert into dump select person, 'B' from list_B; /* dump les éléments de list_B dans la table et marque les par la lettre "B"*/ |
-> "A moins B":
Code:
1 2 3
| select person
from (select * from dump group by person having count(*)='1') as T /* Prends les éléments qui ne sont PAS dans l'intersection ( count='1' ) */
where list_source='A'; /* Prends uniquement les éléments marqués "A" */ |
-> "B moins A":
Code:
1 2 3
| select person
from (select * from dump group by person having count(*)='1') as T /* Prends les éléments qui ne sont PAS dans l'intersection ( count='1' ) */
where list_source='B'; /* Prends uniquement les éléments marqués "B" */ |
-> "intersection de A et B"
Code:
select person from dump group by person having count(*)='2';
Voilà, ... en attendant que MySQL intégre les opérateurs ensemblistes.
Bon courage!
Sibawe
Du nouveau sur ce point ?
Je vais devoir réaliser des intersection multiples. pour ce faire j'hésite entre 2 approches :
1/ tout mettre dans une seule table et je lance ce genre de requête :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| SELECT id_user
FROM ta_table
WHERE id_lieu = 1 AND id_user IN (
SELECT id_user
FROM ta_table
WHERE id_lieu = 2)
AND id_user IN (
SELECT id_user
FROM ta_table
WHERE id_lieu = 3)
AND id_user IN (
SELECT id_user
FROM ta_table
WHERE id_lieu = 4); |
2/ je créé des tables pour chaque lieux et je met les user id et je fais une intersection entre les tables pour déterminer les user_id qui sont communs à ces tables.
Sachant qu'Il y aura plusieurs dizinaines de millier de "users" et des centaines de lieux.
- Y a t-il un intérêt en terme de perf a utiliser la solution 2 ?
- si oui, quelle genre de requête dois-je réaliser ?
- si non, comment optimiser la solution 1 ?