问题描述
我知道这不是第一个“动态交叉表列”问题,但我的具体情况有点不同。
我正在为我的公司设计库存架构,crosstab
似乎是为其生成人类可读摘要的最便捷方式。有很多产品类型不能都放在同一张表中,所以我选择了这样的模式:
-
vendor_products
表,具有唯一的product_id
列和product_type
- 具有
inventory
和 bigserialproduct_id
列(代表产品实例)的中央unique_id
表 - 一个单独的
attribute_types
表,其中包含attr_id
和attr_name
列 - 可以附加到产品实例的任何内容(颜色、mac 地址、序列号等...)进入这里 - 结合
device_attributes
和inventory
表的attribute_types
表。它有 3 列:unique_id
、attr_id
和attr_value
(pkey 是unique_id
+attr_id
)。这是将多个attr_id
及其值映射到相关unique_id
的地方。看起来像:
unique_id | attr_id | attr_value |
---|---|---|
u_1 |
1(颜色) | 蓝色 |
u_1 |
2 (serial#) | 1234567 |
u_2 |
1(颜色) | 黑色 |
u_2 |
2 (serial#) | 7654321 |
这种设计的结果是所有 attr_value
都是 varchars。
假设所有正确的外键都在那里。
现在,我想使用 crosstab()
从这个设计中得到一个人类可读的表格,以查看产品类型的所有实例。程序是:
- 使用
inventory.product_id
对vendor_products.product_type
进行子查询 - 获取
inventory.unique_ids
的结果集 - 使用
unique_id
的集合获取device_attributes
表中的匹配信息并将其交叉表
device_attributes
表已经是函数所需的确切输入形式。标题标题是已知的 - 它们是 attr_name
,对应于附加到产品子集的唯一一组“attr_id”。
唯一的问题是列数会随 product_type
的不同而变化。我发现这个 answer 表明如果可以在执行时给出列的返回类型(第一个建议),则可以制作动态 crosstab
表。如前所述,每一列都是一个 varchar。唯一的问题是为从当前 attr_name
派生的函数提供一种格式,每个函数都附加了一个 varchar。虽然引用的问题表明这是可能的,但它没有链接到实现。
您可以在下面看到我的尝试,“不存在列“product_subset”的错误”,我不知道为什么。 (到现在为止我从来没有做过函数,所以请原谅我的次优设计。我知道这很糟糕)。
是否可以挽救此功能,或者在 Postgres 中是否有另一种方法可以做到这一点?我之所以提出这个问题,是因为我还没有找到关于 crosstab
使用这种类型的架构结构的问题,但我觉得它最有可能奏效。
编辑:稍微修正了该函数,但似乎给定的表类型需要看起来像输出的内容。想知道是否可以在父函数中构造表类型并将其传递给下面的函数。
如果没有,那么我将在后端实现所需的逻辑。非常感谢任何帮助/帮助!
CREATE OR REPLACE FUNCTION getProducts(tbltype anyelement,_id integer)
RETURNS SetoF anyelement
LANGUAGE plpgsql AS
$func$
DECLARE
_cols text := 'id bigint,';
BEGIN
CREATE temporary table product_subset AS (
SELECT * FROM device_attributes
WHERE unique_id IN
(SELECT unique_id FROM inventory
WHERE product_id IN
(SELECT product_id FROM vendor_products
WHERE type_id IN (_id)
)
)
);
_cols := _cols || ( SELECT string_agg(attrt.attr_name,' varchar,')
FROM attribute_types AS attrt
WHERE
attrt.attr_id IN (SELECT disTINCT ps.attr_id FROM product_subset AS ps)
);
_cols := _cols || ' varchar';
raise notice 'Cols: ',_cols; -- For debugging
RETURN QUERY EXECUTE '
SELECT *
FROM crosstab(
''SELECT
ps.unique_id,ps.attr_id,ps.value
FROM
product_subset AS ps
ORDER BY 1''
) AS ct (' || _cols || ')';
END
$func$;
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)