In Postgres I have two tables:
Table A { int keyA, Text name}
Table B { int keyB, int keyA, char mark, date start, date end}
Mark from Table B could be 'X', 'Y', 'Z'. I want to get every record 'X' with dates but only one from 'Y', 'Z'. Also if there are 'X', 'Y', 'Z' i want only 'X'.
From:
keyB | keyA | mark | start | end |
---|---|---|---|---|
1 | 1 | X | 15-01-2023 | 16-01-2023 |
2 | 1 | X | 17-01-2023 | 18-01-2023 |
3 | 1 | Y | null | null |
4 | 1 | Z | null | null |
5 | 2 | Y | null | null |
6 | 2 | Z | null | null |
7 | 2 | Y | null | null |
8 | 3 | Z | null | null |
9 | 3 | Y | null | null |
10 | 4 | X | 19-01-2023 | 20-01-2023 |
I want to get
keyB | keyA | mark | start | end |
---|---|---|---|---|
1 | 1 | X | 15-01-2023 | 16-01-2023 |
2 | 1 | X | 17-01-2023 | 17-01-2023 |
5 | 2 | Y | null | null |
8 | 3 | Z | null | null |
10 | 4 | X | 19-01-2023 | 20-01-2023 |
I tried: 1.
Select A.name,
(select b2.start from B b2 where b2.keyA = A.keyA and b2.mark = 'X') as Start,
(select b2.end from B b2 where b2.keyA = A.keyA and b2.mark = 'X') as End,
from A order by name;
Order is important. I need to have name first. There is a porblem. In subqueries i have more than one record so i have to add limit 1. But I want to get every X not only one.
If I do this
Select A.name, B.start, B.end
from A inner join B on A.keyA = B.keyB
I'll have X, Y, Z and as I mentioned I want only X or one from Y or Z. Any idea how should I solve this?
CodePudding user response:
Use the row_number
function with your join query as the following:
select name, keyB, keyA, mark, start_dt, end_dt
from
(
select A.name, B.*,
row_number() over (partition by B.keyA order by case when B.mark='X' then 1 else 2 end, B.keyb) rn
from tableB B join tableA A
on B.keyA = A.keyA
) T
where mark = 'X' or rn = 1
order by keyb