如何创建一个视图,在不聚合的情况下返回单行中的所有子记录?

问题描述 投票:0回答:0

我是一名电气工程师,开发零件库数据库和资源管理器工具供我的组织内部使用。如果有人熟悉 OrCAD 原理图捕获工具,我基本上是在重新创建 Cadence 的 CIS(组件信息系统)后端和 CIP(组件信息门户)前端,但我试图让它们与 CAD 软件无关(应该与 OrCAD、Altium、KiCAD 一起工作, ETC)。我快到终点线了,但我被数据库视图绊倒了,我需要将数据输入我的 CAD 软件

目前我有 6 个表,每个表都包含关于每个部分的不同类型的数据:

表名 目的 人际关系
课程 零件类别 父到主
主要 CAD 工具的描述性识别信息和数据 班级的孩子,多对一。所有其他表的父级。在其他表中将内部零件号 (IPN) 用作外键。
性能规格 用于自动零件应力降额分析的零件额定值。零件等级决定标准。 main的孩子,一对一
制造业 制造商和零件编号 main 的孩子,多对一
采购 供应商和零件号 main 的孩子,多对一
兼容性 交叉参考备选零件 - 相同的形式、配合和功能,在表面处理、可靠性等级等方面存在细微差异 main 的孩子,多对一

主要问题是CAD软件通过ODBC与数据库通信,无法处理分表的数据。所以我需要创建视图(每个库一个——按类分组)来显示每个表中连接数据的查询。

记录之间的“多对一”关系构成了一个特殊的问题,因为我需要将制造表中的所有子记录与主表中的父记录一起表示在一行中。

我目前有一个视图使用 LEFT JOIN 拉入所有子记录,但制造表中的每个子记录都会创建一个新行。我需要一些方法来查询数据,以便所有子记录都在一行中。

这里是主表和制造表的简化结构以及一些示例数据。

主要

id ipn part_class 零件价值 描述 包装 spec_doc sch_symbol_kicad pwb_fotprint_kicad last_modified_user last_modified_timestamp
1 PRT-00000001 RES, 其他 10k RES、SMT、厚膜、10k、1%、100ppm、0.15 W 0805 资源 resc0805 FLast 2023-05-04 07:38:53.782386-04
2 PRT-00000002 CAP、钽、固态 15u CAP、SMT、钽、220u、10%、10V、可靠性等级 D、浪涌测试选项 C 2214 MIL-PRF-55365/11 cap_p capc2214 FLast 2023-05-03 07:31:05.815801-04

制造业

id ipn 制造商 mpn
1 PRT-00000001 国巨 RC0805JR-0710KL
2 PRT-00000001 Stackpole 电子公司 RNCP0805FTD10K0
3 PRT-00000001 Susumu RG2012P-103-B-T5
4 PRT-00000002 基美 T429F156K020DC4252
5 PRT-00000002 京瓷AVX CWR29JC156KDFC

我想创建一个如下所示的视图:

ipn part_class 零件价值 描述 包装 spec_doc sch_symbol_kicad pwb_fotprint_kicad mfr_1 mpn_1 mfr_2 mpn_2 ... mfr_n mpn_n

如果有人能帮我找出一个查询来构建制造表,其中所有记录都对应于同一行中的同一 IPN,那将是一个巨大的帮助。将它与主表或任何其他表连接起来应该是直截了当的。

提前致谢!

这里有一些重新创建表的 SQL 代码:

CREATE TABLE components.main (
    id integer NOT NULL,
    ipn components.citext DEFAULT to_char(nextval('components.main_ipn_seq'::regclass), '"PRT-"fm00000000'::text) NOT NULL,
    part_class integer NOT NULL,
    part_value components.citext NOT NULL,
    description components.citext NOT NULL,
    spec_doc components.citext,
    sch_symbol_kicad components.citext,
    sch_symbol_altium components.citext,
    pwb_footprint_kicad components.citext,
    pwb_footprint_altium components.citext,
    step_file components.citext,
    lead_frm_reqd boolean DEFAULT false NOT NULL,
    lead_finish components.citext,
    datasheet components.citext,
    last_modified_user components.citext DEFAULT USER NOT NULL,
    last_modified_timestamp timestamp with time zone DEFAULT now() NOT NULL,
    nrnd boolean DEFAULT false NOT NULL,
    bom_exclusion integer DEFAULT 0 NOT NULL,
    pwb_exclusion integer DEFAULT 0 NOT NULL,
    package components.citext
);

ALTER TABLE components.main ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
    SEQUENCE NAME components.main_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1
);

CREATE SEQUENCE components.main_ipn_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

CREATE TABLE components.manufacturing (
    id integer NOT NULL,
    ipn components.citext NOT NULL,
    mfr components.citext NOT NULL,
    mpn components.citext NOT NULL,
    cage components.citext
);

ALTER TABLE components.manufacturing ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (
    SEQUENCE NAME components.manufacturing_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1
);

我研究过旋转和交叉表函数,但我看到的每个示例都对数值数据使用了聚合,这并不直接适用于我。此外,这些示例似乎使用源表中的单个列将数据透视表的列定义为“类别”。我发现很难使这个概念适应我想做的事情,我想将每个 mfr 和 mpn 对视为唯一的。

Edit-002 我想出了如何使用分层查询让视图显示我想要的内容,但它非常慢(~200 条记录约 100-200 毫秒)。任何关于性能优化策略的建议都将不胜感激!

这是我的代码:

CREATE OR REPLACE VIEW components.manf_pair_index
AS
SELECT manufacturing.id,
    manufacturing.ipn,
    manufacturing.mfr,
    manufacturing.mpn,
    row_number() OVER (PARTITION BY manufacturing.ipn ORDER BY manufacturing.id, manufacturing.ipn) AS pair_num
    FROM manufacturing;

CREATE OR REPLACE VIEW components.manf_flat
AS
SELECT manf_pair_index.ipn,
    max(manf_pair_index.mfr) FILTER (WHERE manf_pair_index.pair_num = 1) AS mfr_1,
    max(manf_pair_index.mpn) FILTER (WHERE manf_pair_index.pair_num = 1) AS mpn_1,
    max(manf_pair_index.mfr) FILTER (WHERE manf_pair_index.pair_num = 2) AS mfr_2,
    max(manf_pair_index.mpn) FILTER (WHERE manf_pair_index.pair_num = 2) AS mpn_2,
    max(manf_pair_index.mfr) FILTER (WHERE manf_pair_index.pair_num = 3) AS mfr_3,
    max(manf_pair_index.mpn) FILTER (WHERE manf_pair_index.pair_num = 3) AS mpn_3,
    max(manf_pair_index.mfr) FILTER (WHERE manf_pair_index.pair_num = 4) AS mfr_4,
    max(manf_pair_index.mpn) FILTER (WHERE manf_pair_index.pair_num = 4) AS mpn_4,
    max(manf_pair_index.mfr) FILTER (WHERE manf_pair_index.pair_num = 5) AS mfr_5,
    max(manf_pair_index.mpn) FILTER (WHERE manf_pair_index.pair_num = 5) AS mpn_5
    FROM manf_pair_index
    GROUP BY manf_pair_index.ipn;

CREATE OR REPLACE VIEW components.resistors
AS
SELECT main.ipn,
    main.nrnd,
    main.part_class,
    main.part_value,
    main.description,
    main.package,
    main.spec_doc,
    main.lead_finish,
    main.lead_frm_reqd,
    manf_flat.mfr_1,
    manf_flat.mpn_1,
    manf_flat.mfr_2,
    manf_flat.mpn_2,
    manf_flat.mfr_3,
    manf_flat.mpn_3,
    manf_flat.mfr_4,
    manf_flat.mpn_4,
    manf_flat.mfr_5,
    manf_flat.mpn_5,
    compatibility.comperable_ipn,
    main.sch_symbol_kicad,
    main.sch_symbol_altium,
    main.pwb_footprint_kicad,
    main.pwb_footprint_altium,
    main.step_file,
    main.bom_exclusion,
    main.pwb_exclusion
    FROM main
        LEFT JOIN manf_flat ON main.ipn::text = manf_flat.ipn::text
        LEFT JOIN compatibility ON main.ipn::text = compatibility.ipn::text
    WHERE main.part_class > 28 AND main.part_class < 45
    ORDER BY main.ipn;
sql postgresql pivot pivot-table
© www.soinside.com 2019 - 2024. All rights reserved.