【问题标题】:Joining two one-to-many tables duplicates records连接两个一对多表会重复记录
【发布时间】:2019-03-13 15:31:19
【问题描述】:

我有 3 张桌子,Transaction, Transaction_Items and Transaction_History

Transaction 是父表,Transaction_Items and Transaction_History 是子表,one to many relationship

当我尝试将这些表连接在一起时,如果我有 2+ Transaction_History2+ Transaction_Items 记录,我会得到重复或三次重复的记录结果。

这是我当前使用的 SQL 查询,它可以工作,但让我担心的是,如果将来我必须加入另一个 one-to-many 表,它会再次复制结果。

我找到了解决方法,但我只是想知道是否有更好、更清洁的方法来做到这一点?

结果应该是一个包含 Transaction_Items 和 Transaction_History 的 PostgreSQL JSON 数组

SELECT
    TR.id AS transaction_id,
    TR.transaction_number,
    TR.status,
    TR.status AS status,
    to_json(TR_INV.list),
    COUNT(TR_INV) item_cnt,
    COUNT(THR) tr_cnt,
    json_agg(THR)
FROM transaction_transaction AS TR
LEFT JOIN (
    SELECT
        array_agg(t) list, -- this is a workaround method
        t.transaction_id
    FROM (
        SELECT
            TR_INV.transaction_id      transaction_id,
            IT.id,
            IT.stock_number,
            CAT.key                    category_key,
            ITP.description            description,
            ITP.serial_number          serial_number,
            ITP.color                  color,
            ITP.manufacturer           manufacturer,
            ITP.inventory_model        inventory_model,
            ITP.average_cost           average_cost,
            ITP.location_in_store      location_in_store,
            ITP.firearm_caliber        firearm_caliber,
            ITP.federal_firearm_number federal_firearm_number,
            ITP.sold_price             sold_price
        FROM transaction_transaction_item TR_INV
            LEFT JOIN inventory_item IT ON IT.id = TR_INV.item_id
            LEFT JOIN inventory_itemprofile ITP ON ITP.id = IT.current_profile_id
            LEFT JOIN inventory_category CAT ON CAT.id = ITP.category_id
            LEFT JOIN inventory_categorytype CAT_T ON CAT_T.id = CAT.category_type_id
    ) t
    GROUP BY t.transaction_id
) TR_INV ON TR_INV.transaction_id = TR.id
LEFT JOIN transaction_transactionhistory THR ON THR.transaction_id = TR.id
    AND (THR.audit_code_id = 44 OR THR.audit_code_id = 27 OR THR.audit_code_id = 28)
WHERE TR.store_id = 21
    AND TR.transaction_type = 'Pawn_Loan' AND TR.date_made >= '2018-10-08'
GROUP BY TR.id, TR_INV.list

【问题讨论】:

  • 如果可以 a) 稍微简单地查询一下 b) 提供示例数据和预期输出,那将真的很有帮助。

标签: postgresql postgresql-9.4


【解决方案1】:

你想做的事情可以不使用join来实现,如下图。 因为您的实际表格有很多我不知道也不应该关心的列。我只是创建了它们中最简单的形式来进行演示。

CREATE TABLE transactions (
     tid    serial PRIMARY KEY,
     name   varchar(40) NOT NULL 
);

CREATE TABLE transaction_histories (
     hid    serial PRIMARY KEY ,
     tid    integer REFERENCES transactions(tid),
     history   varchar(40) NOT NULL 
);

CREATE TABLE transaction_items (
     iid    serial PRIMARY KEY ,
     tid    integer REFERENCES transactions(tid),
     item   varchar(40) NOT NULL 
);

INSERT INTO transactions(tid,name) Values(1, 'transaction');

INSERT INTO transaction_histories(tid, history) Values(1, 'history1');
INSERT INTO transaction_histories(tid, history) Values(1, 'history2');

INSERT INTO transaction_items(tid, item) Values(1, 'item1');
INSERT INTO transaction_items(tid, item) Values(1, 'item2');


select
t.*,

(select count(*) from transaction_histories h where  h.tid= t.tid) h_count ,
(select json_agg(h) from transaction_histories h where  h.tid= t.tid) h ,

(select count(*) from transaction_items i where  i.tid= t.tid) i_count ,
(select json_agg(i) from transaction_items i where  i.tid= t.tid) i

from transactions t;

【讨论】:

    猜你喜欢
    • 2023-04-10
    • 1970-01-01
    • 2014-12-04
    • 2022-11-13
    • 2013-12-09
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    相关资源
    最近更新 更多