mysql - 如何连接多个表并使用一个表中的数据来创建输出列?

标签 mysql laravel

我正在使用 Laravel 和 MySQL 构建一个错误跟踪系统,到目前为止我有 3 个表

  • fillers as f:保存填充符 id、名字和姓氏列:
    • id,= el.tech,
    • 名字,
    • 姓氏
  • error_type as et:保存一个表来描述可能的错误类型并分配一个 id 列:
    • ID,
    • 名称 = el.error_id
  • error_logs as el:保存所有填充列的所有错误:
    • ID,
    • error_id, =et.name
    • 技术,=f.id
public function countAllLogs()
{
    $errorLog = DB::table('fillers AS f')
        ->select(
            'f.id as id',
            'f.first_name as first_name',
            'f.last_name as last_name',
            // 'f.location as location',
            'et.name as error_type',
        )
        ->selectRaw(
            'count(el.error_id) as count', 
        )
        ->groupBy('f.id')
        ->groupBy('el.error_id')
        ->leftjoin('error_logs as el', 'f.id', '=', 'el.tech')
        ->leftjoin('error_types as et', 'et.id', '=', 'el.error_id')
        ->get();

    return response($errorLog, 200);
}

使用Postman Get函数给出以下示例

    {
        "id": 59,
        "first_name": "Steve",
        "last_name": "Martian",
        "error_type": "ndc",
        "count": 3
    },
    {
        "id": 59,
        "first_name": "Steve",
        "last_name": "Martian",
        "error_type": "jumper",
        "count": 1
    }

这几乎就是我想要的,但它根据“error_type”分开。我见过“pivot”,但不确定如何用我所拥有的来实现它。

期望的输出是

    {
        "id": 59,
        "first_name": "Steve",
        "last_name": "Martian",
        "jumper": 1,
        "ndc": 3
    }

谢谢。

最佳答案

您可以使用 flatMap 集合方法来实现此目的。我假设会出现多个 id,因此也会使用 groupBymap

$errorLog = DB::table('fillers AS f')->...->get();

$json = $errorLog
    ->groupBy('id')
    ->map->flatMap(fn($item) => [
        'id' => $item->id,
        'first_name' => $item->first_name,
        'last_name' => $item->last_name,
        $item->error_type => $item->count
    ])
    ->values()
    ->toJson();

return response($json, 200);

说明

这是原始集合。我添加了几个条目来演示不同的 id。

array:4 [
  0 => {#4540
    +"id": 59
    +"first_name": "Steve"
    +"last_name": "Martian"
    +"error_type": "ndc"
    +"count": 3
  }
  1 => {#4567
    +"id": 59
    +"first_name": "Steve"
    +"last_name": "Martian"
    +"error_type": "jumper"
    +"count": 1
  }
  2 => {#4569
    +"id": 57
    +"first_name": "qwer"
    +"last_name": "Martian"
    +"error_type": "ndc"
    +"count": 3
  }
  3 => {#4573
    +"id": 58
    +"first_name": "asdf"
    +"last_name": "Martian"
    +"error_type": "jumper"
    +"count": 1
  }
]

groupBy('id'):按 id 对集合进行分组。这对于下一步很重要。

array:3 [
  59 => Illuminate\Support\Collection {#4592
    #items: array:2 [
      0 => {#4540
        +"id": 59
        +"first_name": "Steve"
        +"last_name": "Martian"
        +"error_type": "ndc"
        +"count": 3
      }
      1 => {#4567
        +"id": 59
        +"first_name": "Steve"
        +"last_name": "Martian"
        +"error_type": "jumper"
        +"count": 1
      }
    ]
  }
  57 => Illuminate\Support\Collection {#4557
    #items: array:1 [
      0 => {#4569
        +"id": 57
        +"first_name": "qwer"
        +"last_name": "Martian"
        +"error_type": "ndc"
        +"count": 3
      }
    ]
  }
  58 => Illuminate\Support\Collection {#4591
    #items: array:1 [
      0 => {#4573
        +"id": 58
        +"first_name": "asdf"
        +"last_name": "Martian"
        +"error_type": "jumper"
        +"count": 1
      }
    ]
  }
]

flatMap(Closure):映射集合,然后折叠它。与map(Closure)->collapse()相同。

map->flatMap(fn($item) => [...]):简写

map(function ($grouped) {
    return $grouped->flatMap(function ($item) {
        return [...];
    });
});

由于高阶收集方法,这种表示法才成为可能。

如果 groupBy 步骤未完成,那么您最终会得到一个项目,数据完全混合在一起。

这是 map->flatMap(Closure) 之后 Collection 的样子:

array:3 [
  59 => Illuminate\Support\Collection {#4590
    #items: array:5 [
      "id" => 59
      "first_name" => "Steve"
      "last_name" => "Martian"
      "ndc" => 3
      "jumper" => 1
    ]
  }
  57 => Illuminate\Support\Collection {#4570
    #items: array:4 [
      "id" => 57
      "first_name" => "qwer"
      "last_name" => "Martian"
      "ndc" => 3
    ]
  }
  58 => Illuminate\Support\Collection {#4588
    #items: array:4 [
      "id" => 58
      "first_name" => "asdf"
      "last_name" => "Martian"
      "jumper" => 1
    ]
  }
]

values():丢弃数组键。这很重要,因为如果 toJson() 尝试保存键,它会生成一个 json 对象而不是 json 数组。

您可以通过一个简单的实验亲自看到这一点:比较之间的结果

  • json_encode([ ['a' => 2, 'b' => 3] ]);
  • json_encode([1 => ['a' => 2, 'b' => 3] ]);
array:3 [
  0 => Illuminate\Support\Collection {#4590
    #items: array:5 [
      "id" => 59
      "first_name" => "Steve"
      "last_name" => "Martian"
      "ndc" => 3
      "jumper" => 1
    ]
  }
  1 => Illuminate\Support\Collection {#4570
    #items: array:4 [
      "id" => 57
      "first_name" => "qwer"
      "last_name" => "Martian"
      "ndc" => 3
    ]
  }
  2 => Illuminate\Support\Collection {#4588
    #items: array:4 [
      "id" => 58
      "first_name" => "asdf"
      "last_name" => "Martian"
      "jumper" => 1
    ]
  }
]

toJson():将集合转换为 json 字符串:(我添加了换行符以提高可读性)

[
  {
    "id":59,
    "first_name":"Steve",
    "last_name":"Martian",
    "ndc":3,
    "jumper":1
  },
  {
    "id":57,
    "first_name":"qwer",
    "last_name":"Martian",
    "ndc":3
  },
  {
    "id":58,
    "first_name":"asdf",
    "last_name":"Martian",
    "jumper":1
  }
]

关于mysql - 如何连接多个表并使用一个表中的数据来创建输出列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70586676/

相关文章:

php - 尝试检索最小值时出现 mysql "select"问题

php - Laravel 查询生成器上的子查询 Where 条件

laravel队列作业多次运行同一个作业

javascript - 显示数据库中的数据而不重新加载

mysql - 如何将营业时间存储在数据库中以便在打开时能够进行搜索?

php - 避免 PHP 中的重复值

mysql - 排序插入数据库的最佳选择

php - 从特定类别 codeigniter 中选择产品

php - Laravel Redis 错误

php - Laravel Eloquent 将查询拆分为数组