选择在 wp_usermeta 表中的多行上具有合格数据的用户

问题描述 投票:0回答:3

我正在尝试找到具有所有四个限定值的

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

php mysql wordpress group-by pivot
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


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_*
函数不是SQL注入保存的,将被弃用。 如果您想尽可能少地更改代码,可以使用
mysqli_
函数: http://php.net/manual/en/book.mysqli.php

推荐:

使用该表中的索引。

user_id
强烈建议使用 和 索引,并建议使用
meta_key
AND
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       |
 +---------+

所以它应该有效。


0
投票

您的表结构是在首选最大数据灵活性时选择的。这种结构的缺点是效率受到影响,表通常会因数据而变得非常臃肿,并且查询表通常涉及使用称为“pivot”的技术的聚合函数。

以下是如何使用数据透视表来执行查询:(db-fiddle demo)

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 之后进行的地方(其中过滤发生在 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;

© www.soinside.com 2019 - 2024. All rights reserved.