【问题标题】:How to get one set of data from a SQL query from multiple table?如何从多个表的 SQL 查询中获取一组数据?
【发布时间】:2020-08-23 06:32:59
【问题描述】:

我的表结构是

TABLE_1
|------|------|-------|
|  ID  | NAME | PHONE | = 1 ROW
|------|------|-------|
TABLE_2
|------|------------|----------|
|  ID  | TABLE_1_ID | CATEGORY | = 5 ROW
|------|------------|----------|
TABLE_3
|------|------------|----------|
|  ID  | TABLE_1_ID | ADDRESS  | = 3 ROW
|------|------------|----------|

我正在使用上表。但我的结果生成 1 行,但在 CATEGORY 单元格中显示 5 CATEGORY 但它重复 3 次,在 ADDRESS 单元格中,3 个地址重复 5 次,如下所示 -

RESULT
|----|------|-------|----------------------------|------------------|
|    |      |       |                            | (ADR1,ADR2,ADR3) |
|    |      |       | (CAT1,CAT2,CAT3,CAT4,CAT5) | (ADR1,ADR2,ADR3) |
| ID | NAME | PHONE | (CAT1,CAT2,CAT3,CAT4,CAT5) | (ADR1,ADR2,ADR3) |
|    |      |       | (CAT1,CAT2,CAT3,CAT4,CAT5) | (ADR1,ADR2,ADR3) |
|    |      |       |                            | (ADR1,ADR2,ADR3) |
|----|------|-------|----------------------------|------------------|

我的 PHP+SQL 是

$db = new Database;
$getData = "SELECT a.name, a.phone, b.category, c.address
FROM table_1 a JOIN table_2 b JOIN table_3 c
WHERE a.id = b.table_1_id AND a.id = c.table_1_id
ORDER BY a.id ASC";
$execute = $db->select($getData);
$result        = [];
$currentParent = false;
$data          = null;
foreach ($execute as $row) {
    if ($currentParent != $row['id']) {
        if($data != null){ 
            $result[]= $data;
        }
        $data = [
            'name'     => $row['name'],
            'phone'    => $row['phone'],
            'category' => '',
            'address'  => ''
        ];
        $currentParent = $row['id'];
    }
    $data['category'] = empty($data['category']) ? $row['category'] : $data['category'] .", ". $row['category'];
    $data['address']  = empty($data['address'])  ? $row['address']  : $data['address']  .", ". $row['address'];
}
$result[]= $data;
echo json_encode($result);

现在的问题是,我将如何在结果中实现 1 组 5 个类别和 1 组 3 个地址。提前致谢。

我的数据

TABLE_1 DATA
|------|------|-------|
|  ID  | NAME | PHONE |
|------|------|-------|
|  1   | JON  | 123   |
|------|------|-------|
TABLE_2 DATA
|------|------------|----------|
|  ID  | TABLE_1_ID | CATEGORY |
|------|------------|----------|
|  1   |      1     |   CAT1   |
|------|------------|----------|
|  2   |      1     |   CAT2   |
|------|------------|----------|
|  3   |      1     |   CAT3   |
|------|------------|----------|
|  4   |      1     |   CAT4   |
|------|------------|----------|
|  5   |      1     |   CAT5   |
|------|------------|----------|
TABLE_3 DATA
|------|------------|----------|
|  ID  | TABLE_1_ID | ADDRESS  |
|------|------------|----------|
|   1  |      1     |   ADR1   |
|------|------------|----------|
|   2  |      1     |   ADR2   |
|------|------------|----------|
|   3  |      1     |   ADR3   |
|------|------------|----------|

我对@9​​87654325@的新查询

SELECT a.id, a.name, a.phone, 
 GROUP_CONCAT(b.category ORDER BY b.category SEPARATOR ',') category,
 GROUP_CONCAT(c.address ORDER BY c.address SEPARATOR ',') address
    FROM table_1 a INNER JOIN table_2 b ON (a.id = b.table_1_id) INNER JOIN table_3 c ON (a.id = c.table_1_id)
    GROUP BY a.id, a.name, a.phone

这个查询也产生同样的结果,我的 PHP 和上面的一样。

【问题讨论】:

  • 我不确定你期待什么输出
  • 如果您正在使用连接(并且应该),您还应该通过包含 ON 子句来正确使用它们..
  • 我用我的表格数据更新了我的问题。

标签: php mysql sql


【解决方案1】:

我将尝试仅使用 SQL 来回答。

将 group_concat 与 distinct 一起使用,

select t.id,name,phone,
 group_concat(distinct a.addr separator ',') as address,
 group_concat(distinct c.cat separator ',') as category
  from table1 t
  left join address a 
    on t.id = a.refid
  left join category c
    on t.id = c.refid
  group by t.id,name, phone

作为内联列,

select t.id,name,phone,
 (select group_concat(a.addr separator ',')
    from address a 
   where a.refid = t.id) as address,
 (select group_concat(c.cat separator ',') 
    from category c
   where c.refid = t.id) as category
  from table1 t

参考Db<>fiddle

【讨论】:

  • 组连接有字符限制限制,请在您的回答中提及这一点以及如何增加此限制
  • 感谢您的提示,但这不是问题的一部分,我现在不想提供更多信息。
  • 因为如果地址长度超过组连接的默认限制会导致信息丢失
  • 以上查询(第一个)正在工作,它显示 1 组类别和 1 组地址。
【解决方案2】:

您的查询涉及多个连接,这就是您获得多行类别和地址的原因,在您的应用程序代码中,您可以通过调整现有逻辑来显示一组类别和地址。

table_1 的每个项目维护类别和地址($categories,$addresses) 的临时变量,并使用in_array() 确保没有重复的地址和类别添加到您的临时变量$categories &amp; $addresses 和内部循环中,当您的迭代从一个项目到另一个项目,然后创建一个逗号分隔的先前收集的类别和地址的字符串

$currentParent = false;
$data          = null;
$categories =$addresses = [];
foreach ($execute as $row) {
    if ($currentParent != $row['id']) {
        if($data != null){ 
            $data['category'] = implode (", ", $categories);
            $data['address'] = implode (", ", $addresses);
            $result[]= $data;
            $categories =$addresses = [];
        }
        $data = [
            'name'     => $row['name'],
            'phone'    => $row['phone'],
            'category' => '',
            'address'  => ''
        ];
        $currentParent = $row['id'];
    }
    if (in_array($row['category'], $categories) === false) {
        array_push($categories, $row['category']);
    }
    if (in_array($row['address'], $addresses) === false) {
        array_push($addresses, $row['address']);
    }
}

$data['category'] = implode (", ", $categories); // for last item
$data['address'] = implode (", ", $addresses); // for last item
$result[]= $data;
echo json_encode($result);

【讨论】:

  • 此代码未在类别和地址字段中显示任何数据。但它的显示名称和电话字段。
  • @Bearded 我的坏 array_push 使用 $data 而不是 $row
  • 它运行良好。非常感谢您的帮助。
【解决方案3】:

由于您没有提供完整的数据,我只能建议您可以在 MYSQL 中使用 GROUP_CONCAT 函数。

所以你的查询将是这样的。

Demo

    SELECT a.id, a.name, a.phone, 
 GROUP_CONCAT( distinct b.cat ORDER BY b.cat SEPARATOR ',') category,
 GROUP_CONCAT(distinct c.addr ORDER BY c.addr SEPARATOR ',') address
    FROM table1 a INNER JOIN category b ON (a.id = b.refid) INNER JOIN address c ON (a.id = c.refid )
    GROUP BY a.id, a.name, a.phone;

【讨论】:

  • 您能否分享您对所有三个表的查询和示例数据。
  • 我已经根据提供的数据更新了我的答案并添加了演示。请检查。
  • 您的查询结果不准确。您必须在 group_concat 内使用 distinct 才能获得准确的结果。请参阅@Sujitmohanty30 的答案。
  • 已根据您的 cmets 更新。
猜你喜欢
  • 2020-11-29
  • 1970-01-01
  • 2013-07-15
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多