48

我试图找到user_id具有所有四个限定值的那个——每个都在数据库表的不同行中。

我正在查询的表是wp_usermeta

Field       Type                   Null    Key    Default    Extra
---------------------------------------------------------------------------
umeta_id    bigint(20) unsigned            PRI               auto_increment
user_id     bigint(20) unsigned            IND    0  
meta_key    varchar(255)           Yes     IND    NULL   
meta_value  longtext               Yes            NULL   

我写了一个 MySQL 查询,但它似乎没有工作,因为结果是空的。

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

如何返回与user_id所有这四行相关的?

4

3 回答 3

58

我会使用这个查询:

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

这将选择user_id满足所有四个条件的所有内容。

于 2013-04-27T08:40:37.217 回答
28

@fthiella 的解决方案非常优雅。

如果将来您想要显示的内容超出了user_id您可以使用的连接,并且一行中可能包含您需要的所有数据。

如果要使用AND条件,并且条件在表中的多行中,则可以使用JOINS示例:

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'

其他:推荐使用prepared statements,因为mysql_*functions不是SQL注入保存,会被弃用。如果你想尽可能少地改变你的代码,你可以使用mysqli_函数: http: //php.net/manual/en/book.mysqli.php

推荐:

使用此表中的索引。user_id强烈建议使用和索引,也建议使用meta_keyAND meta_value,以便更快地运行查询。

解释:

如果您使用AND“连接”一条线路的条件。因此,如果您想要多行的 AND 条件,首先您必须从多行创建一行,就像这样。

测试:表数据:

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

$us_name='Kovge' $us_yearselect='2012' $us_reg='GaPa'用,查询的结果$us_course='PHP'

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

所以它应该有效。

于 2013-04-27T08:05:57.213 回答
0

您正在查询一个表,该表被设计为我所见过的被称为“统一内容模型”(UCM)的表。当首选最大数据灵活性时选择此表结构。这种结构的缺点是效率受损,表通常会因数据非常臃肿而受到影响,并且查询表通常涉及使用称为“枢轴”的技术的聚合函数。

以下是如何使用枢轴执行查询:(db-fiddle 演示

SELECT user_id 
FROM wp_usermeta
GROUP BY user_id
HAVING MAX(IF(meta_key = 'first_name', meta_value, NULL)) = 'mangesh'
   AND MAX(IF(meta_key = 'yearofpassing', meta_value, NULL)) = '2013'
   AND MAX(IF(meta_key = 'u_city', meta_value, NULL)) = 'n/a'
   AND MAX(IF(meta_key = 'us_course', meta_value, NULL)) = 'programming'

实际上,整个表按user_id列分组。在此过程中,形成了一种临时的一对多关系。换句话说,每个相应user_id的将有一个或多个行的数据(非线性,不平坦),可以由 MySQL 的聚合函数(例如MAX())查询。

HAVING 子句是过滤逻辑必须在 GROUP BY 之后进行的地方(WHERE 过滤发生在 GROUP BY 之前)。在“数据集群”中,您可以通过检查数据来隔离数据meta_key。当您找到与 匹配的行时meta_key,您使用其meta_value,如果不是,则分配一个有区别的默认值。在聚合中的所有行都已被 处理后IF,您知道您要查找的行是非 NULL 值——这是通过调用来访问的MAX()。使用此最大值与您过滤的实际值进行比较。根据需要重复此过滤器以满足您的业务逻辑。

我还应该声明,您没有使用安全编码实践。 mysql_query()目前已弃用,并且出于任何原因不应存在于任何当前活动的代码中。我建议您使用 mysqli 的面向对象语法并实现带有绑定参数的准备好的语句,以实现安全性/稳定性。

$sql = "SELECT user_id 
        FROM wp_usermeta
        GROUP BY user_id
        HAVING MAX(IF(meta_key = 'first_name', meta_value, NULL)) = ?
           AND MAX(IF(meta_key = 'yearofpassing', meta_value, NULL)) = ?
           AND MAX(IF(meta_key = 'u_city', meta_value, NULL)) = ?
           AND MAX(IF(meta_key = 'us_course', meta_value, NULL)) = ?";

$stmt = $conn->prepare($sql);
$stmt->bind_param('ssss', $us_name, $us_yearselect, $us_reg, $us_course);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($user_id);
$stmt->fetch();
echo $user_id;
于 2021-04-26T19:40:25.830 回答