【发布时间】:2022-01-03 16:49:57
【问题描述】:
我正在使用 SQL 查询来连接同一张表的多行并选择相关列(仅限 NOT NULL 列)。 以下是您必须了解的有关我的表的信息:
我想要实现的是检索所有产品及其所有属性(命名)。 为了说明,如果我有 2 个属性名为“attribute_1”和“attribute_2”,最终结果应该如下所示:
{
"id" => 1,
"attribute_1" => "The attribute value", //The attribute value can be stored in any column suffixed by "_value"
"attribute_2" => "The attribute value" //The attribute value can be stored in any column suffixed by "_value"
}
我正在使用 Laravel 和 ATM,这就是我正在做的事情:
//First retrieve all attribute names
$attribute_names = Attribute::select('name')->pluck('name');
//Build the final select statement that will be used
foreach ($attribute_names as $attribute_name) {
$select_array[] = DB::raw("MAX(CASE WHEN name='" . $attribute_name . "' THEN value ELSE NULL END) as " . $attribute_name);
}
//Sub query to select only the right column (the one that is not NULL)
$sub_query_select_only_not_null_columns = DB::table('attributes')
->leftJoin('product_attribute_values', 'product_attribute_values.attribute_id', 'attributes.id')
->select(
DB::raw('CASE
WHEN text_value IS NOT NULL THEN text_value
WHEN boolean_value IS NOT NULL THEN boolean_value
WHEN integer_value IS NOT NULL THEN integer_value
WHEN float_value IS NOT NULL THEN float_value
WHEN datetime_value IS NOT NULL THEN datetime_value
WHEN date_value IS NOT NULL THEN date_value
WHEN json_value IS NOT NULL THEN json_value
END AS value
'),
'attributes.name',
'product_attribute_values.product_id as product_id'
);
//Final query
Products::leftJoin('products', 'product_flat.product_id', '=', 'products.id') //Ignore this join
->leftJoinSub($sub_query_select_only_not_null_columns, 'mysubquery', function ($join) {
$join->on('products.id', '=', 'mysubquery.product_id');
})->select($select_array)->groupBy('products.id')
此查询有效,但存在一些问题:
- 我必须先查询所有属性名称(对我来说不是真正的问题,但仍然)
- 如果我没有在主查询中使用某些产品 id 进行过滤 ->whereIn('products.id',[1,2,3,4,5,6]) 那么看起来子查询正在检索所有所有产品的属性值和查询需要一段时间。即使我限制了主查询,子查询也会获取所有产品的所有product_attribute_values。
所以这是我的问题:
- 有没有办法通过一个查询来实现所有这些?
- 我应该改用 SQL 视图吗?
- 如果我想坚持我的查询,我应该怎么做才能只获取与将出现在结果中的产品相关的 product_attribute_values ?
- 对于那个 SQL 架构,什么是做我想做的最好的方法?
这个问题解释/理解有点复杂。如果您需要,我可以提供更多信息。 PS:由于查询有点长,我没有提供SQL,但我可以分享一下。
提前致谢!
【问题讨论】:
-
感觉可以使用 group_concat 或 union 找到解决方法,但最重要的是,如果会有这么多的空值,那可能不是一个好的设计。如果可能,应优先考虑标准化。如果可以选择,我会将 attr_values 表更改为具有
type字段和value字段。因此,例如对于浮点值type将是float并且value将具有它的值,依此类推。不再需要担心排除空值。然后这又归结为偏好和可能性。 -
感谢您的评论!事实上,设计已经在 Bagisto(电子商务 PHP 模块)中完成了,我无法真正修改模型定义,因为我们在我的公司将它用于其他项目......感谢您的建议!
-
介意分享一个样本数据集吗?
标签: php mysql sql laravel eloquent