2010-01-19 11 views
1

Avoir ce tableau (désolé, cant semblent obtenir un aménagement correct ici):problème Tricky SQL SELECT (MySQL)

PD  Header   Text    Mask_Producer  Mask_Dep  Mask_Diam 
---------------------------------------------------------------------------------------------- 
10  Producer  Aproducer   Aprod    *    * 
10  Producer  Bproducer   Bprod    *    * 
20  Diam   A     Aprod    10    30 
20  Diam   A     Aprod    20    40 
20  Diam   B     Aprod    10    40 
30  Dep   10    Aprod    10    * 
30  Dep   20    Aprod    20    * 
30  Dep   30    Aprod    30    * 
20  Diam   A     Bprod    20    40 
30  Dep   10    Bprod    10    * 

J'utilise les lignes de la table comme un filtre/masque pour sélectionner d'autres lignes .

Ainsi, l'utilisateur ayant déjà fait une sélection de lignes avec:

PD Text 
------------- 
10 Aproducer 
20 A 

Je voudrais maintenant savoir ce que les lignes avec PD = 30 correspond aux choix précédents:

PD = 10, Texte = Aproducer indique que Mask_Producer doit être "Aprod", (Mask_Dep et Mask_Diam peuvent être n'importe quoi par les étoiles)

PD = 20, Texte = A indique que Mask_Producer doit être "Aprod" et Mask_Dep doit être 10 ou 20 et Mask_Diam doit être 30 ou 40 (ou étoile)

Je veux que le résultat soit les lignes 6 et 7 du tableau ci-dessus.

Alors imaginez cet exemple avec 2000rows et 20 champs Mask_xx ....

Je pense SQL comme IN, LEFT JOIN, JOIN et tables temporaires pour ce faire, mais je pense que je suis trop compliquer les choses beaucoup ....

+0

rendre le code de données, (4 places) donc au moins en rend monospaces. –

+0

Merci de ne pas utiliser les onglets - la syntaxe markdown: http://stackoverflow.com/editing-help –

+1

Je ne comprends pas quelles sont les règles que vous essayez de capturer dans votre requête. Par exemple, pourquoi les lignes 6 et 7 devraient-elles être la sortie désirée? Je ne vois pas le motif. – recursive

Répondre

0

Ceci est la type de code que j'utilise en utilisant, ça marche, mais comme j'ajoute plus de critères et de champs je reçois plus de jointures énormes et dans chaque jointure aussi plus de AND..OR ... OU de séquences, donc les propositions d'améliorations sont les bienvenues! Surtout que je suis consernde que cela peut être lent que les données grovs? L'analyse de ce que le serveur sql doit faire pour mon code est la bienvenue!

Actuellement, j'ai environ 30 critères/champs et du code PHP qui génère la requête SQL pour moi ....

Mais voici le plus petit exemple du principe:

SELECT DISTINCT t30.* 
FROM 
    (SELECT * 
    FROM YourTable 
    WHERE PD = 10 
    AND Text = 'Aproducer') AS t10 
JOIN 
    (SELECT * 
    FROM YourTable 
    WHERE PD = 20 AND Text = 'A') AS t20 ON 
    (t20.MaskProducer = t10.MaskProducer 
           OR t20.MaskProducer = '*' 
           OR t10.MaskProducer = '*') 
    AND (t20.MaskDep = t10.MaskDep 
           OR t20.MaskDep = '*' 
           OR t10.MaskDep = '*') 
    AND(t20.MaskDiam = t10.MaskDiam 
           OR t20.MaskDiam = '*' 
           OR t10.MaskDiam = '*') 
//more JOINS like the one above for each criteria 
// below the final join to get the result from 
JOIN 
    (SELECT * 
    FROM YourTable 
    WHERE PD = 30) AS t30 ON 
     (t30.MaskProducer = t20.MaskProducer 
          OR t30.MaskProducer = '*' 
          OR t20.MaskProducer = '*') 
     AND (t30.MaskDep = t20.MaskDep 
          OR t30.MaskDep = '*' 
          OR t20.MaskDep = '*') 
     AND (t30.MaskDiam = t20.MaskDiam 
          OR t30.MaskDiam = '*' 
          OR t20.MaskDiam = '*'); 
1

Je pense que je comprends ce que vous demandez, mais je suis plus familier avec SQL Server, donc si ma syntaxe est un peu petite s'il vous plaît pardonnez-moi. Vous devriez être capable de faire une jointure interne, en rejoignant la table à elle-même pour obtenir les résultats que vous voulez. En regardant cela, je pense que je suis un peu à l'écart, mais certaines de vos données ne sont pas claires. Pourriez-vous donner des règles plus universelles pour ce que vous cherchez dans Mask_Dep et Mask_Diam?

+0

Salut, vous pourriez être sur quelque chose, mais A.PD = B.Mask_Dep est clairement pas correct, ces champs ne sont pas liés .... –

+0

Point pris. Il semble que les règles pour A.PD et B.PD sont différentes. Est-ce le cas? Sinon pourriez-vous me donner une règle unifiée? Je pense que si vous le pouvez, je pourrais probablement vous aider. –

+0

Vous avez obtenu cette résolu d'une autre source (rob_farley): SELECT t30. * FROM (SELECT * DE YourTable WHERE PD = 10 ET Texte = 'Aproducer') que t10 JOIN (SELECT * FROM YourTable WHERE PD = 20 ET Text = ' A ') en tant que t20 ON (t20.MaskProducer = t10.MaskProducer OU t20.MaskProducer =' * 'OU t10.MaskProducer =' * ') ET (t20.MaskDep = t10.MaskDep OU t20.MaskDep =' * 'OU t10 .MaskDep = '*') ET (t20.MaskDiam = t10.MaskDiam OU t20.MaskDiam = '*' OU t10.MaskDiam = '*') ... suite dans le commentaire suivant .... –

1

Je pense que vous voulez quelque chose comme ceci:

SELECT r.* FROM table AS c -- choices 
JOIN table AS r   -- results 
    ON (
     (r.mas_dep = '*' OR c.mask_dep = r.mask_dep) 
     AND 
     (r.mask_diam = '*' OR c.mask_diam = r.mask_diam) 
    ) 
WHERE (
    (c.pd = 10 AND c.text = 'Aproducer') 
    OR (c.pd = 20 AND c.text = 'A') 
) 
AND r.PD = 30 

Cela prendra le résultat des choix:

PD  Header   Text   Mask_Producer Mask_Dep Mask_Diam 
10  Producer  Aproducer Aprod   *   * 
20  Diam    A   Aprod   10   30 
20  Diam    A   Aprod   20   40 

Et autojointure contre la table principale, où ces conditions sont vraies r.mas_dep = '*' OR c.mask_dep = r.mask_dep et r.mask_diam = '*' OR c.mask_diam = r.mask_diam. Ceci renvoie un ensemble de:

PD  Header   Text   Mask_Producer Mask_Dep Mask_Diam 
30  Dep    10   Aprod   10   * 
30  Dep    20   Aprod   20   * 

Il exclut les autres clairement parce que leurs mask_deps de 30 ne sont pas dans le choix resultset, et il exclut les lignes non 30.

Pds
+0

Cela ressemble à vous me dérangez! Va penser et essayer et vous faire savoir. Merci pour le moment, faut dormir ... ;-) –

+0

Salut, Evan, maintenant testé, fonctionne presque! .... si j'ajoute ces rangées # 9: "20 Diam A Bprod 20 40" et # 10: "30 Dep 10 Bprod 10 *" J'obtiendrai # 9 dans les choix (faux) et ensuite # 10 inclus dans le résultat (faux) .... des suggestions? –