Замена выбранных значений значениями из других таблиц - PullRequest
1 голос
/ 09 мая 2020

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

    create table customers (
        cpr VARCHAR(10) PRIMARY KEY,
        name VARCHAR(100) NOT NULL
    );

    CREATE TABLE accounts (
        id SERIAL PRIMARY KEY,
        balance INT DEFAULT 0,
        customerCpr VARCHAR(10) references customers (cpr) NOT NULL,
    );

    CREATE TABLE transactions(
        id SERIAL PRIMARY KEY,
        retriever INT references accounts (id) NOT NULL,
        giver     INT references accounts (id) NOT NULL,
        timestamp timestamp default current_timestamp,
        amount    INT NOT NULL
    );

Итак, я хочу запросить что-то вроде

SELECT retrieverCustomer.name, giverCustomer.name, tran.timestamp tran.amount 
FROM transactions tran 
WHERE tran.retriever = 20 OR tran.giver = 20...

I хочу, чтобы он возвращал этот формат:

 id | retName   | gName |         timestamp          | amount 
----+-----------+-------+----------------------------+--------
  1 | Elisabeth | Jonas | 2020-05-09 11:07:50.614155 |   1500
  2 |  Veronica | Peter | 2020-05-09 11:07:50.614155 |   2200
  3 |Kristoffer | Jens  | 2020-05-09 11:07:50.614155 |   1700

Я не уверен, как этого добиться, я пробовал с некоторым присоединением и некоторыми условными выражениями, но мне не удалось увидеть проблему. Если кто-то знает, как этого добиться или может объяснить, почему это не идеально, это действительно поможет мне.

Ответы [ 2 ]

1 голос
/ 09 мая 2020

Вы хотите присоединиться к таблице учетных записей и клиентов дважды, один раз как даритель, один раз как получатель:

SELECT cr.name as retriever_customer, cg.name as giver_customer, t.timestamp, t.amount 
FROM transactions t
JOIN accounts ar on ar.id = t.retriever
JOIN accounts ag on ag.id = t.giver
JOIN customers cr on cr.cpr = ar.customercpr
JOIN customers cg on cg.cpr = ag.customercpr
WHERE t.retriever = 20 OR t.giver = 20
ORDER BY t.timestamp;
0 голосов
/ 09 мая 2020

Это место, где CTE может оказаться более ясным:

with ac as (  -- accounts with the customer name added on
      select a.*, c.name
      from accounts a join
           customers c
           on a.customercpr = c.cpr
     )
select t.id, acg.name as giver_name, acr.name as retriever_name, t.timestamp, t.amount
from transactions t join
     ac acg
     on acg.id = t.giver join
     ac acr
     on acr.id = t.retriever 
where 20 in (t.giver, t.retriever);
...