web-dev-qa-db-fra.com

Requête de sélection MySQL avec plusieurs conditions

J'ai écrit une requête MySQL mais cela ne semble pas fonctionner car le résultat est vide. Y a-t-il une erreur dans mon code?

$result = mysql_query(
     "SELECT user_id 
      FROM wp_usermeta 
      WHERE 
         (meta_key = 'first_name' AND meta_value = '$us_name') AND         
         (meta_key = 'yearofpassing' AND meta_value = '$us_yearselect') AND 
         (meta_key = 'u_city' AND meta_value = '$us_reg') AND 
         (meta_key = 'us_course' AND meta_value = '$us_course')"
);
40
Mangesh Narayankar

Je voudrais utiliser cette requête:

SELECT
  user_id
FROM
  wp_usermeta 
WHERE 
  (meta_key = 'first_name' AND meta_value = '$us_name') OR 
  (meta_key = 'yearofpassing' AND meta_value = '$us_yearselect') OR 
  (meta_key = 'u_city' AND meta_value = '$us_reg') OR
  (meta_key = 'us_course' AND meta_value = '$us_course')
GROUP BY
  user_id
HAVING
  COUNT(DISTINCT meta_key)=4

cela sélectionnera tous les user_id qui remplit les quatre conditions.

46
fthiella

La solution de @fthiella est très élégante.

Si à l’avenir vous voulez montrer plus que user_id vous pouvez utiliser des jointures et toutes les données dont vous avez besoin peuvent se trouver sur une seule ligne.

Si vous voulez utiliser AND conditions et que les conditions sont dans plusieurs lignes de votre table, vous pouvez utiliser JOINS exemple:

SELECT `w_name`.`user_id` 
     FROM `wp_usermeta` as `w_name`
     JOIN `wp_usermeta` as `w_year` ON `w_name`.`user_id`=`w_year`.`user_id` 
          AND `w_name`.`meta_key` = 'first_name' 
          AND `w_year`.`meta_key` = 'yearofpassing' 
     JOIN `wp_usermeta` as `w_city` ON `w_name`.`user_id`=`w_city`.user_id 
          AND `w_city`.`meta_key` = 'u_city'
     JOIN `wp_usermeta` as `w_course` ON `w_name`.`user_id`=`w_course`.`user_id` 
          AND `w_course`.`meta_key` = 'us_course'
     WHERE 
         `w_name`.`meta_value` = '$us_name' AND         
         `w_year`.meta_value   = '$us_yearselect' AND 
         `w_city`.`meta_value` = '$us_reg' AND 
         `w_course`.`meta_value` = '$us_course'

Autre chose: Recommander d'utiliser des déclarations préparées, car mysql_* fonctions n'est pas une sauvegarde d'injection SQL et sera obsolète. Si vous voulez changer votre code le moins possible, vous pouvez utiliser mysqli_ fonctions: http://php.net/manual/en/book.mysqli.php

Recommandation:

Utilisez les index dans cette table. user_id recommande fortement d’être indexé et recommandé d'être le meta_key ET meta_value _ aussi, pour une exécution plus rapide de la requête.

Le expliquer:

Si vous utilisez AND, vous 'connectez' les conditions pour une ligne. Donc, si vous voulez ET conditionner pour plusieurs lignes, vous devez d’abord créer une ligne à partir de plusieurs lignes, comme ceci.

Tests: Données de la table:

          PRIMARY                 INDEX
      int       varchar(255)    varchar(255)
       /                \           |
  +---------+---------------+-----------+
  | user_id | meta_key      | meta_value|
  +---------+---------------+-----------+
  | 1       | first_name    | Kovge     |
  +---------+---------------+-----------+
  | 1       | yearofpassing | 2012      |
  +---------+---------------+-----------+
  | 1       | u_city        | GaPa      |
  +---------+---------------+-----------+
  | 1       | us_course     | PHP       |
  +---------+---------------+-----------+

Le résultat de Query avec $us_name='Kovge'$us_yearselect='2012'$us_reg='GaPa', $us_course='PHP':

 +---------+
 | user_id |
 +---------+
 | 1       |
 +---------+

Donc ça devrait marcher.

25
Kovge

vous pouvez aussi utiliser "ET" au lieu de "OU" si vous voulez que les deux attributs soient appliqués.

select * from tickets where (assigned_to='1') and (status='open') order by created_at desc;
3
Adam Falchetta