datajoe / postgresql-distinct-on
为 Laravel 提供对 PostgreSQL 特定的 DISTINCT ON 特性的支持。兼容版本 5 至 8。
Requires
- php: ^7.4|^8.0
- ext-pdo: *
- laravel/framework: ^5.0|^6.0|^7.0|^8.0|^9.0
Requires (Dev)
This package is auto-updated.
Last update: 2024-09-30 01:29:48 UTC
README
它做了什么
- 为 Laravel 5-9 提供对 PostgreSQL 特定的 DISTINCT ON 特性的支持。
SELECT DISTINCT ON (表达式[, ...]) 只保留每个集合中给定表达式评估为相等的行的第一行。DISTINCT ON 表达式使用与 ORDER BY 相同的规则解释(见上文)。注意,除非使用 ORDER BY 确保所需行首先出现,否则每个集合中“第一行”是不可预测的。
例如
SELECT DISTINCT ON (location) location, time, report FROM weather_reports ORDER BY location, time DESC;
检索每个位置的最新天气报告。但如果我们没有使用 ORDER BY 来强制每个位置的时间值的降序排列,我们可能会得到每个位置的不可预测时间的报告。
DISTINCT ON 表达式必须与最左边的 ORDER BY 表达式匹配。ORDER BY 子句通常包含额外的表达式,用于确定每个 DISTINCT ON 组内行的所需优先级。
为什么需要它?
我专门构建这个,因为我想要一个描述性元数据表,允许我保留给定键的所有版本的数据。我需要能够轻松地检索存储值的最新版本。Postgres 通过支持 SELECT DISTINCT ON 使这变得非常容易,然而 Laravel/Eloquent 没有对此数据库特定功能提供基本支持。
如何使用它
在您的项目目录中运行:
composer require datajoe/postgresql-distinct-on在您的 app.php 中,将
Illuminate\Database\DatabaseServiceProvider::class,替换为DataJoe\Extensions\Illuminate\Database\DatabaseServiceProvider::class,在您的代码中,您可以使用
->distinctOn('field_name')方法访问 DISTINCT ON 功能。请确保也在您的查询中包含->orderBy('field_name')!
示例
这将返回每个 distinct meta_name 的单个 RecordMeta 行,其中只包含最新 update_at 时间戳,对于记录_id 为 1 的每个不同 meta_name
$fields = RecordMeta::select(['record_id', 'value', 'updated_at'])
->distinctOn('meta_name')
->where('record_id', 1)
->orderBy('meta_name')
->orderBy('updated_at', 'desc');
该命令等价于以下 SQL
SELECT DISTINCT ON ('meta_name') meta_name, record_id, value, updated_at
FROM record_meta
WHERE record_id = 1
ORDER BY meta_name, updated_at DESC;
您还可以做的事情
要能够通过模型关系访问元数据(例如,Record -> RecordMeta),您可以在您的记录模型中添加以下内容以建立自定义关系
public function recordMeta()
{
$relation = $this->hasMany(RecordMeta::class);
$relation->getQuery()
->select(['record_id', 'value', 'updated_at'])
->distinctOn('meta_name')
->orderBy('updated_at', 'desc');
return $relation;
}
然后,在您的代码中,您可以像这样访问元数据
$record = Record::with('recordMeta')->get();
然后您将得到所有记录,其中每个记录的每个 meta_name 都只包含最近设置的值。