【问题标题】:Syntax for joining multiple tables连接多个表的语法
【发布时间】:2015-01-16 06:35:37
【问题描述】:

我需要根据特定的WHERE 条件从 3 个不同的表中查询行。

我的桌子是:

  • 地区
  • 个人资料
  • 用户元

profiles 表有两个外键,user_id 和 region_id,它们引用了下表。

users 表有一个 id、first_name 和 last_name 列。我还需要为配置文件表中具有 id 的每一行获取 first_name 和 last_name。

regions 表有一个 name 和 id 列。我需要获取配置文件表中具有相应 id 的每个区域的名称。

在配置文件表中,我还有我需要的列 id、certs 和 title。

现在我用三个单独的查询来提取这些,效率太低了。我知道我可以使用 JOINS 来做到这一点,但我不确定语法应该是什么。

更新:

经过你们的大量帮助并进行了一些额外的挖掘,这里是 PHP 和 WordPress 格式的查询的正确代码:

    $select_sql = "SELECT p.id, p.title, concat( u1.meta_value, ' ', u2.meta_value ) as fullname, concat( r.name, ', ', c.name ) as location";
    $from_sql   = "FROM {$modules->tables->profiles} p";
    $join_sql   = "LEFT JOIN {$wpdb->usermeta} u1 ON p.user_id = u1.user_id AND u1.meta_key = 'first_name'";
    $join_sql  .= " LEFT JOIN {$wpdb->usermeta} u2 ON p.user_id = u2.user_id AND u2.meta_key = 'last_name'";
    $join_sql  .= " LEFT JOIN {$modules->tables->regions} r ON r.id = p.region_id";
    $join_sql  .= " LEFT JOIN {$modules->tables->countries} c ON c.id = p.country_id";
    $where_sql  = "WHERE p.certification IN ( '%s' ) AND p.country_id IN ( %d )";
    $orderby_sql= "ORDER BY p.user_id ASC";

    $q = $wpdb->prepare( "{$select_sql} {$from_sql} {$join_sql} {$where_sql} {$orderby_sql}", $certification, $country_id );
    $results = $wpdb->get_results( $q );

$q 上的 var_dump 为我们提供了以下 SQL:

string(515) "SELECT p.id, p.title, concat( u1.meta_value, ' ', u2.meta_value ) as fullname, concat( r.name, ', ', c.name ) as location FROM modules_profiles p LEFT JOIN moonlight_usermeta u1 ON p.user_id = u1.user_id AND u1.meta_key = 'first_name' LEFT JOIN moonlight_usermeta u2 ON p.user_id = u2.user_id AND u2.meta_key = 'last_name' LEFT JOIN modules_regions r ON r.id = p.region_id LEFT JOIN modules_countries c ON c.id = p.country_id WHERE p.certification IN ( 'certified' ) AND p.country_id IN ( 2 ) ORDER BY p.user_id ASC"

【问题讨论】:

  • 多个JOINs 的语法与仅一个的语法没有什么不同。

标签: mysql sql wordpress join


【解决方案1】:

连接的语法如下所示:

SELECT stuff
FROM firstTable
JOIN secondTable ON firstTable.someColumn = secondTable.matchingColumn

在这种情况下,我还建议使用表别名(只需在表名后添加别名就足够了)。这只是朝着正确方向的简单推动:

SELECT columnsYouNeed
FROM users u
JOIN profiles p ON p.user_id = u.id
JOIN regions r ON r.id = p.region_id;

这是您正在寻找的语法,我将挑战您正确输入列并添加您可能需要的任何 WHERE 子句。如果您仍然卡住,请随时提出问题。

【讨论】:

  • @McAdmin331 我在上面的问题中添加了新的 sql。我可以在没有 usermeta 的情况下使用它,但是一旦我将该表放入混合中,什么都不会返回。
【解决方案2】:

在所有表格之间执行JOIN。以下查询是您在帖子中提供的信息的集合

select users.first_name,
users.last_name,
regions.name,
profiles.id, 
profiles.certs, 
profiles.title
from users 
left join profiles on profiles.user_id = users.id
left join region on profiles.region_id = regions.id;

【讨论】:

  • 我在上面的问题中添加了新的 sql。我可以在没有 usermeta 的情况下使用它,但是一旦我将该表放入混合中,什么都不会返回。
  • @TonyaLUNARWP,在这种情况下,请使用LEFT JOIN,而不是像LEFT JOIN moonlight_usermeta u ON u.user_id = p.user_id。类似于我编辑的答案。
  • 没有骰子。 u.first_name 和 u.last_name 不在除 usermeta 之外的任何其他数据库表中。并且 r.name 仅在区域中。
  • @TonyaLUNARWP,你得到一个空集,因为你正在做一个inner join,它只给出匹配的结果。如果不匹配,那么你会得到空结果,所以你需要像左/右外连接这样的外连接。
  • 我将 JOIN 都更改为 LEFT JOIN,但结果仍然为空。
【解决方案3】:

正如你所说的使用 JOINs

以下是基于假设用户可能必须拥有个人资料或地区的查询。

SELECT users.first_name, users.last_name, regions.name,  profiles.id, profiles.certs, profiles.title
FROM users
LEFT JOIN profiles ON profiles.user_id = users.id
LEFT JOIN regions ON regions.id = profiles.region_id

如果他们总是这样,或者你只想要那些有个人资料和地区的人,那么你可以将其更改为 INNER JOIN

【讨论】:

  • 我在上面的问题中添加了新的 sql。我可以在没有 usermeta 的情况下使用它,但是一旦我将该表放入混合中,什么都不会返回。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多