使用PostgreSQL,我有很多查询,如下所示:
SELECT <col 1>, <col 2>
, (SELECT sum(<col x>)
FROM <otherTable>
WHERE <other table foreignkeyCol>=<this table keycol>) AS <col 3>
FROM <tbl>
Run Code Online (Sandbox Code Playgroud)
鉴于子选择在每种情况下都是相同的,有没有办法将该子选择存储为表中的伪列?基本上,我希望能够从表A中选择一列,它是表B中与记录相关的特定列的总和.这可能吗?
我正在尝试加快对 PostgreSQL 数据库中存储的一些 json 数据的查询速度。我继承了一个应用程序,该应用程序查询一个名为 的 PostgreSQL 表,该data表带有一个名为 的字段value,其中值是类型为 json 的 blob jsonb。
它大约有 300 行,但从 5 个 json 元素中选择此数据需要 12 秒。json blob 有点大,但我需要的数据都在 json 嵌套的顶层(如果有帮助的话)。
我尝试添加索引,CREATE INDEX idx_tbl_data ON data USING gin (value);但这没有帮助。我应该使用不同的索引吗?长期愿景是重写应用程序以将数据移出 json,但由于应用程序其他部分的复杂性,这至少需要 30-40 个工作日的工作,所以我想看看是否可以可以在短期内加快速度。
不确定它是否有帮助,但构成此结果集的基础数据不会经常更改。经常发生变化的是 json blob 中更下方的数据。
SELECT
value::json ->> 'name' AS name,
value::json ->> 'mnemonic' AS mnemonic,
value::json ->> 'urlName' AS "urlName",
value::json ->> 'countryCode' AS "countryCode",
value::json #>>'{team}' AS team
FROM
data;
Run Code Online (Sandbox Code Playgroud) 外键的语法,如官方文档中所述,包括表 A 中的列集引用表 B 中的列集。
是否可以在外键声明中使用常量?
问题是,我有表 DICTIONARIES,其中包含所有字典值,按类型区分。我知道这不是一个好的设计,但不幸的是,我没什么可说的,因为数据库管理员想要“最小化表的数量”......
是否有可能实现类似的目标:
CREATE TABLE PERSON (
id integer primary key,
country_id integer,
...
FOREIGN KEY ('COUNTRY', country_id) REFERENCES DICTIONARIES(TYPE, ID)
)
Run Code Online (Sandbox Code Playgroud)
就可以有效解决这个问题。我知道我可以向表 person 添加列,该表只有一个可能的值“COUNTRY”,或者我可以编写一个触发器,但我宁愿避免这种情况以保持设计简洁。
CREATE TABLE my_app.person
(
person_id smallserial NOT NULL,
first_name character varying(50),
last_name character varying(50),
full_name character varying(100) generated always as (concat(first_name, ' ', last_name)) STORED,
birth_date date,
created_timestamp timestamp default current_timestamp,
PRIMARY KEY (person_id)
);
Run Code Online (Sandbox Code Playgroud)
Error: generation expression is not immutable
The goal is to populate the first name and last into the full name column.
sql postgresql database-design string-concatenation calculated-columns
我一直处于这种困境中一段时间,但是找不到任何提示,尽管似乎有人已经做到了。
我需要的是用加密的安全(即非连续!)ID替换顺序的AUTO_INCREMENT(或等效的)主键,但与此同时,我想保留顺序PK的性能优势:保证未使用的下一个ID,可集群性等。
一种简单的方法似乎实现了一种加密伪随机排列生成器,以将2 ^ N空间唯一地映射到2 ^ N,而不会发生冲突并且具有初始化矢量(IV)。
尽管可以在外部实现,但这确实需要存储和原子访问状态(排列位置或最后一个ID),这意味着从外部实现效率极低(这相当于UPDATE table SET crypto_id = FN_CRYPTO(autoincrement_id) WHERE autoincrement_id=LAST_INSERT_ID()为每个都运行后续操作INSERT)。
您是否知道在商业用途的数据库中有上述任何上述实现?
我想在我的表上为start_time创建一个索引,这是我的 json 列中名为match的 timestamptz (带时区的时间戳)字段。
在这个问题和这篇文章之后,我了解到由于不同的时区和本地化,您无法在 timestamptz 字段上创建索引。这两个都表明您可以在时间戳(转换为文本)上创建索引,因此我尝试了以下功能:
CREATE OR REPLACE FUNCTION to_text(timestamptz)
RETURNS text AS $$
SELECT to_char($1 at time zone 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.US')
$$
LANGUAGE sql IMMUTABLE;
Run Code Online (Sandbox Code Playgroud)
我相信这与时区和本地化没有问题。
CREATE INDEX i_match_start_time ON matches (to_text(((match->>'start_time')::timestamptz)));
Run Code Online (Sandbox Code Playgroud)
这将返回以下内容:
错误:索引表达式中的函数必须标记为 IMMUTABLE
我还尝试过返回时间戳的函数:
SELECT ($1 at time zone 'UTC')
Run Code Online (Sandbox Code Playgroud)
以及返回 unix 时间的函数(尝试了 double 并转换为十进制):
SELECT EXTRACT(EPOCH FROM $1)
Run Code Online (Sandbox Code Playgroud)
其中每个都返回相同的错误。
我需要在start_time上建立索引,因为实际上对该表的所有选择查询都将按start_time排序。
我正在尝试进行队列分析,并根据承租人的第一个租赁年份(=承租人第一次租赁的年份)比较平均租金。基本上,我在问一个问题:我们是否保留第一年是2013年的房客而不是第一年是2015年的房客?
这是我的代码:
SELECT renter_id,
Min(Date_part('year', created_at)) AS first_rental_year,
( Count(trip_finish) ) AS number_of_trips
FROM bookings
WHERE state IN ( 'approved', 'aboard', 'ashore', 'concluded', 'disputed' )
AND first_rental_year = 2013
GROUP BY 1
ORDER BY 1;
Run Code Online (Sandbox Code Playgroud)
我收到的错误消息是:
ERROR: column "first_rental_year" does not exist
LINE 6: ... 'aboard', 'ashore', 'concluded', 'disputed') AND first_rent...
^
********** Error **********
ERROR: column "first_rental_year" does not exist
SQL state: 42703
Character: 208
Run Code Online (Sandbox Code Playgroud)
任何帮助深表感谢。
我正在尝试这个表达式,但我没有找到我的语法错误的地方:
alter table "TableName"
add column "NameColumn" as concat(ColumnA,ColumnB,ColumnC)
Run Code Online (Sandbox Code Playgroud)
所有三个字段都是字符变化的。
我有这个查询来获取表上的索引列表:
SELECT
ns.nspname as schema_name,
tab.relname as table_name,
cls.relname as index_name,
am.amname as index_type,
idx.indisprimary as is_primary,
idx.indisunique as is_unique
FROM
pg_index idx
INNER JOIN pg_class cls ON cls.oid=idx.indexrelid
INNER JOIN pg_class tab ON tab.oid=idx.indrelid
INNER JOIN pg_am am ON am.oid=cls.relam
INNER JOIN pg_namespace ns on ns.oid=tab.relnamespace
WHERE ns.nspname = @Schema AND tab.relname = @Name
Run Code Online (Sandbox Code Playgroud)
它似乎工作正常。但现在我需要对列列表进行查询,但我无法理解系统视图的工作方式。
具体来说,我正在寻找的是:
理想情况下,我想一次获得给定表的所有索引的上述项目。
请注意,我正在寻找的不仅仅是列名。
在数据库中存储计算字段的最佳实践是什么。
例如,假设一张桌子有高度,重量,体重指数等字段
用户输入身高体重值,并自动填写bmi字段。如何用表格实现。
bmi $ bmi的公式=体重/(身高*身高)
尝试了以下配置文件模型
protected $table = 'profiles';
protected $fillable = ['user_id', 'weight', 'height', 'dob', 'age', 'bmi'];
public function user(){
return $this->belongsTo(User::class, 'user_id');
}
protected static function boot() {
parent::boot();
static::saving(function($model){
$model->bmi = $model->weight / ($model->height * $model->height);
$model->age = (date('Y') - date('Y',strtotime($model->dob)));
});
}
Run Code Online (Sandbox Code Playgroud)
配置文件控制器
public function store(Request $request)
{
$profile = new Profile();
$profile->weight = $request->get('weight');
$profile->height = $request->get('height');
$profile->dob = $request->get('dob');
$profile->age;
$profile->bmi;
$profile->save();
return back()->with('success', 'Your profile has been updated.');
}
Run Code Online (Sandbox Code Playgroud)
但是我收到一个错误
Illuminate …Run Code Online (Sandbox Code Playgroud) 我已经给出了一些来自 PHP 的例子,只是为了指出我的开发环境。问题不是关于 PHP,而是纯粹关于 PostgreSQL。
生成的列有两种:存储的和虚拟的。存储的生成列在写入(插入或更新)时进行计算,并像普通列一样占用存储空间。虚拟生成列不占用存储空间,读取时进行计算。
但是,它只显示了该页面示例中存储列的示例,而不是虚拟列。它还说:
必须指定关键字 STORED 来选择生成列的存储类型。有关更多详细信息,请参阅创建表。
...链接到CREATE TABLE 页面的地方。在该页面中,文档明确指出模式是GENERATED ALWAYS AS (expression) STORED.
GENERATED ALWAYS AS ( generation_expr ) 存储
此子句将列创建为生成的列。该列无法写入,读取时将返回指定表达式的结果。
需要关键字 STORED 来表示该列将在写入时计算并将存储在磁盘上。
生成表达式可以引用表中的其他列,但不能引用其他生成的列。使用的任何函数和运算符都必须是不可变的。不允许引用其他表。
我实际上尝试在 Laravel (PHP) 中实现一个虚拟字段,这是我迄今为止在迁移中想到的:
DB::statement('ALTER TABLE entries ADD COLUMN do_hint BOOLEAN GENERATED ALWAYS AS (hint_hash OR hint_tags OR hint_due_date OR hint_created_at OR hint_updated_at) VIRTUAL');
Run Code Online (Sandbox Code Playgroud)
正如您在此语句中所见,表中有hint_hash,hint_tags和其他几个布尔列(以hint_*glob 模式命名)entries。我想计算do_hint即时,以便:
postgresql ×9
sql ×7
json ×2
create-table ×1
cryptography ×1
database ×1
datetime ×1
foreign-keys ×1
indexing ×1
jsonb ×1
laravel ×1
pgadmin ×1
view ×1