由于懒惰和方便,我在我的 PostgreSQL 数据库中以不受限制的数字类型集成了来自合作伙伴的大量数据。
然而,现在看来,根据该合作伙伴的不同出货量,数字的比例从零到超过 20 个小数位(或比例)不等,这没有多大意义,可能会无缘无故地消耗大量存储空间. 所以我想将我的数字字段限制在一个合理的范围内。
然而,因为我的合作伙伴没有提供任何建议,我想确定我的数据集中每个尺度的出现,以可能在 0 和 20 之间确定一个合理的中间地带(零显然不是一个选项,并且考虑到 1700 万行-算,总金额将受到我的决定的影响)。
在接下来的四舍五入过程中也需要使用它,以避免实际增加标度为零的值的标度。
长话短说,对于存储为任意数字的特定数字,计算它的最佳方法是什么?
我能想到的最好的方法是,但有没有更优雅的方法可以在不转换为文本的情况下做到这一点?
SELECT
my_numeric,
COALESCE(
char_length( -- Finding size of string extracted by a...
substring(my_numeric::text,'\.(\d*)') -- regexp to return all digits right from '.'
), -- but if scale is 0 substring return NULL
0 -- so I handled this inside a COALESCE
) AS my_numeric_scale
FROM
(VALUES
(0.1::numeric),
(0.12),(0.123),
(0.1234),
(0.12345),
(0.123456),
(0.000001),
(0.100000)
) foo …
Run Code Online (Sandbox Code Playgroud) 在开发和测试期间,VALUES 文字表达式非常有用,因为它们使您能够在 SQL 查询中存储数据定义。
WITH foobar(foo, bar) AS (
VALUES
(1::integer,'a'::text),
(2,'b'),
(3,'c'),
(4,'d')
)
SELECT * FROM foobar;
Run Code Online (Sandbox Code Playgroud)
然而,当尝试使用非常宽或大的表时,这可能会变得乏味。如果这可以从现有表中生成,那就更令人沮丧了。
所以我有一种方法可以轻松地将行作为文字 VALUES 表达式复制/粘贴吗?
我能得到的最接近的是输出行作为记录
(请注意元数据,因为此 SQL 实际上尝试从给定的文字 VALUES 反向工程文字 VALUES)。
WITH foobar(foo, bar) AS (
VALUES
(1::integer,'a'::text),
(2,'b'),
(3,'c'),
(4,'d')
)
SELECT foobar::record FROM foobar;
Run Code Online (Sandbox Code Playgroud)
这是 psql 输出:
foobar
--------
(1,a)
(2,b)
(3,c)
(4,d)
(4 rows)
Run Code Online (Sandbox Code Playgroud)
然而,这需要额外的编辑来正确引用、键入和转义内容,所以我应该寻找格式化输出技巧还是 SQL 技巧?
编辑:当前的最佳答案已经非常好,但理想情况下,我想知道是否有通用方法来生成可以适应您可以抛出的任何记录类型的值表达式(即使它是带有随机数的复合行列)。
假设可以将其包装为如下函数:
row_to_values(IN myrowtype record, OUT myrowtype_as_literal_values text)
Run Code Online (Sandbox Code Playgroud)
在这个阶段,人们可能想知道“为什么不使用 row_to_json() ?” 是的,这可能是一个有效的替代方案,但我们正在偏离我想到的初始用例(快速生成用于测试/偶尔目的的 SQL),尽管使用 json 应该表现良好并且现在在 PostgreSQL 版本中广泛可用。
更好的是一个聚合函数,它直接输出一个干净的文本定义,在第一个 VALUE 上指定类型并添加列名作为别名(但在这个阶段,它几乎是一个功能提案,这里不是正确的地方,我没有人问对于这样的事情)。 …