Объединение двух одинаковых таблиц дублирует записи - PullRequest
0 голосов
/ 09 октября 2018

У меня есть 3 таблицы, Transaction, Transaction_Items and Transaction_History.

Где Transaction - родительская таблица, а Transaction_Items and Transaction_History - дочерние таблицы, с one to many relationship.

Когда япопробуйте объединить эти таблицы вместе, если у меня есть 2+ Transaction_History записей или 2+ Transaction_Items я получаю дублированные или тройные результаты записей.

Это SQL-запрос, который я сейчас использую, который работает, но что меня беспокоит вбудущее, если мне придется присоединиться к другой таблице one-to-many, результаты снова будут дублироваться.

Я нашел обходной путь для этого, но мне было просто интересно, есть ли лучший и более чистый способсделать это?

Результаты должны быть массивом JSON PostgreSQL, который будет содержать Transaction_Items и Transaction_History

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

1 Ответ

0 голосов
/ 09 октября 2018

То, что вы хотите сделать, может быть достигнуто без использования объединений, как показано ниже.Потому что в ваших реальных таблицах столько столбцов, что я не знаю, и мне все равно.Я просто создал их простейшие формы для демонстрации.

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;
...