我有一个表,persons它包含两列,一个id和一个基于 JSONB 的data列(这个表只是为了演示目的而制作的,以使用 PostgreSQL 的 JSON 支持)。
现在,假设它包含两条记录:
1, { name: 'John', age: 30 }
2, { name: 'Jane', age: 20 }
Run Code Online (Sandbox Code Playgroud)
现在,假设我想得到每个 25 岁以上的人的名字。我尝试过的是:
select data->'name' as name from persons where data->'age' > 25
Run Code Online (Sandbox Code Playgroud)
不幸的是,这会导致错误。我可以通过使用->>代替来解决它->,但是比较不再按预期工作,因为不是比较数字,而是比较它们作为字符串的表示:
select data->'name' as name from persons where data->>'age' > '25'
Run Code Online (Sandbox Code Playgroud)
然后我发现我实际上可以通过使用->和强制转换来解决这个问题int:
select data->'name' as name from persons where cast(data->'age' as int) > 25
Run Code Online (Sandbox Code Playgroud)
这有效,但我必须知道实际类型并不是那么好(ageJSON 文档中的类型是number无论如何,那么为什么 PostgreSQL …
我正在尝试运行以下查询以提供patients表中具有refinst列值的行的百分比。我一直得到0的结果。
select (count (refinst) / (select count(*) from patients) * 100) as "Formula"
from patients;
Run Code Online (Sandbox Code Playgroud)
该表有 15556 行,并select count(refinst) from patients告诉我其中 1446行在列中有值refinst。我想从查询中得到的响应是 30.62 ( 1446/15556*100=30.62XXXXX,四舍五入到两位小数)。
我很确定它与计数结果的数据类型(我假设是整数)有关。如果我将一个整数除以一个整数并且结果小于 0,它会被截断为 0 是否正确?如果是这种情况,有人可以告诉我如何将计数结果转换为带有 2 个小数位的数字,以便结果也四舍五入到 2 个小数位吗?
我确信有比多个 count 语句更好的方法来编写此代码。我正在寻找一种更高效的方式来编写这个查询。
表中的每一行都有一个系统列 ctid,其类型tid表示该行的物理位置:
Run Code Online (Sandbox Code Playgroud)create table t(id serial); insert into t default values; insert into t default values;
Run Code Online (Sandbox Code Playgroud)select ctid , id from t;ctid | ID :---- | -: (0,1) | 1 (0,2) | 2
dbfiddle在这里
从ctid最合适的类型(例如integer,bigint或numeric(1000,0))中获取页码的最佳方法是什么?
在我能想到的唯一的办法是非常难看。
我varchar在 SQL Server 的表中有一个列,其中包含一个 base64 编码的文本字符串,我想将其解码为纯文本等效项
SQL Server 是否具有处理此类事情的任何本机功能?
一个示例 base64 字符串:
cm9sZToxIHByb2R1Y2VyOjEyIHRpbWVzdGFtcDoxNDY4NjQwMjIyNTcxMDAwIGxhdGxuZ3tsYXRpdHVkZV9lNzo0MTY5ODkzOTQgbG9uZ2l0dWRlX2U3Oi03Mzg5NjYyMTB9IHJhZGl1czoxOTc2NA==
Run Code Online (Sandbox Code Playgroud)
解码为:
role:1 producer:12 timestamp:1468640222571000 latlng{latitude_e7:416989394 longitude_e7:-738966210} radius:19764
Run Code Online (Sandbox Code Playgroud) sql-server t-sql sql-server-2008-r2 cast string-manipulation
Microsoft SQL Server 有一个我认为非常明智的函数,如果转换不成功,try_cast()它返回一个null,而不是引发错误。
这使得可以使用CASE表达式或 acoalesce来回退。例如:
SELECT coalesce(try_cast(data as int),0);
Run Code Online (Sandbox Code Playgroud)
问题是,PostgreSQL 有没有类似的东西?
提出这个问题是为了填补我知识中的一些空白,但也有一个一般原则,即有些人更喜欢对某些用户错误做出不那么剧烈的反应。null在 SQL 中返回 a比错误更容易。例如SELECT * FROM data WHERE try_cast(value) IS NOT NULL;。根据我的经验,如果有 B 计划,有时可以更好地处理用户错误。
我有一个助手,它正在生成一些代码来为我进行批量更新,并生成如下所示的 SQL:
( active 和 core 字段都是 type boolean)
UPDATE fields as t set "active" = new_values."active","core" = new_values."core"
FROM (values
(true,NULL,3419),
(false,NULL,3420)
) as new_values("active","core","id") WHERE new_values.id = t.id;
Run Code Online (Sandbox Code Playgroud)
但是它失败了:
ERROR: column "core" is of type boolean but expression is of type text
我可以通过添加::boolean空值来让它工作,但这看起来很奇怪,为什么 NULL 被认为是类型TEXT?
此外,转换有点棘手,因为它需要对代码进行大量修改才能知道它应该将 NULL 转换为什么类型(列和值的列表目前是从一个简单的 JSON 对象数组自动生成的) .
为什么这是必要的,是否有更优雅的解决方案,不需要生成代码知道 NULL 的类型?
如果相关,我将在Node.JS上使用sequelize来执行此操作,但在 Postgres 命令行客户端中也得到相同的结果。
在讨论这个问题的递归 CTE 解决方案时:
@ypercube偶然发现了一个令人惊讶的异常,这导致我们调查类型修饰符的处理。我们发现了令人惊讶的行为。
即使被指示不要这样做。最基本的例子:
SELECT 'vc8'::varchar(8)::varchar
Run Code Online (Sandbox Code Playgroud)
人们可能会期望varchar(没有修饰符),至少我会。但结果是varchar(8)(带修饰符)。下面的小提琴中有许多相关的案例。
不需要,所以这在相反的一面出错:
SELECT ARRAY['vc8']::varchar(8)[]
, ARRAY['vc8']::varchar(8)[] || 'vc8'::varchar(8)
Run Code Online (Sandbox Code Playgroud)
第一个表达式varchar(8)[]按预期产生。
但是第二个,在连接另一个之后varchar(8)被淡化到只是varchar[](没有修饰符)。来自array_append(),下面小提琴中的示例的类似行为。
在大多数情况下,所有这些都无关紧要。Postgres 不会丢失数据,并且当分配给列时,该值无论如何都会被强制转换为正确的类型。然而,相反方向的错误最终会导致一个令人惊讶的异常:
鉴于此简化表:
CREATE TABLE a (
vc8 varchar(8) -- with modifier
, vc varchar -- without
);
INSERT INTO a VALUES ('a', 'a'), ('bb', 'bb');
Run Code Online (Sandbox Code Playgroud)
虽然此 rCTE 对varchar列有效vc,但对 …
我想从 ARGV[] 转换到 PostgreSQL 中的 int 数组,我在代码中用TODO标记了伪代码。x86_64-unknown-linux-gnu 上 PostgreSQL 9.4.3 中的代码,由 gcc (Debian 4.9.2-10) 4.9.2 编译,64 位:
CREATE TABLE measurements (
measurement_id SERIAL PRIMARY KEY NOT NULL,
measurement_size_in_bytes INTEGER NOT NULL
);
CREATE TABLE events (
event_id SERIAL PRIMARY KEY NOT NULL,
measurement_id INTEGER NOT NULL,
event_index_start INTEGER NOT NULL,
event_index_end INTEGER NOT NULL
);
CREATE OR REPLACE FUNCTION insaft_function()
RETURNS TRIGGER AS
$func$
BEGIN
-- TODO Loop until TG_ARGV[0] empty
INSERT INTO events (measurement_id, event_index_start, event_index_end)
SELECT …Run Code Online (Sandbox Code Playgroud) 我经常看到人们谈论"char"。我从来没有用过它。它在文档中定义为,
“char”类型(注意引号)与 char(1) 的不同之处在于它只使用一个字节的存储空间。它在系统目录中作为一种简单的枚举类型在内部使用。
并进一步,
"char" 1 byte single-byte internal type
Run Code Online (Sandbox Code Playgroud)
那么,如果它是一个字节,那么域是什么,您将如何使用它?它是签名的还是未签名的?在@Erwin Brandstetter 的这篇文章中,他对此进行了阐述,但我仍然感到困惑。他正在使用ascii()and chr(),并提供了这个
SELECT i
, chr(i)::"char" AS i_encoded
, ascii(chr(i)::"char") AS i_decoded
FROM generate_series(1,256) i;
Run Code Online (Sandbox Code Playgroud)
这在 10 点到 11 点之间做一些非常奇怪的事情。
i | i_encoded | i_decoded
-----+-----------+-----------
...
8 | \x08 | 8
9 | | 9
10 | +| 10
| | -- WTF is going on here.
11 | \x0B | 11
12 | \x0C | 12 …Run Code Online (Sandbox Code Playgroud) double precision从( float8) 到numeric四舍五入到 15 个有效小数位的转换,从而丢失信息。显然,更高的精度是可能的。转换为bigint(对于其范围内的值)可以保留更高的精度:
SELECT f8 AS float8
, f8::bigint AS to_bigint
, f8::numeric AS to_numeric
FROM (
VALUES
('8217316934885843456'::float8)
, ('8217316934885843457')
, ('8217316934885844479')
, ('8217316934885844480')
, ('8217316934885845503')
, ('8217316934885845584')
) t(f8);
float8 | to_bigint | to_numeric
-----------------------+---------------------+---------------------
8.217316934885843e+18 | 8217316934885842944 | 8217316934885840000
8.217316934885844e+18 | 8217316934885843968 | 8217316934885840000
8.217316934885844e+18 | 8217316934885843968 | 8217316934885840000
8.217316934885845e+18 | 8217316934885844992 | 8217316934885840000
8.217316934885845e+18 | 8217316934885844992 | 8217316934885840000
8.217316934885846e+18 | 8217316934885846016 | 8217316934885850000
(6 rows)
Run Code Online (Sandbox Code Playgroud)
db<>在这里摆弄 …