select [date], id,
max(case when type='comm' then currency end) as Comm_cur,
max(case when type='exch' then currency end) as Exch_cur
from myTable
group by [date], id;
Here is DBFiddle demo
EDIT: How it works?
If we removed MAX() and GROUP BY:
select [date], id,
case when [type]='comm' then currency end as Comm_cur,
case when [type]='exch' then currency end as Exch_cur
from myTable;
would give this result:
| date |
id |
Comm_cur |
Exch_cur |
| 2023-01-12 |
1 |
usd |
null |
| 2023-01-12 |
1 |
null |
usd |
| 2023-01-19 |
2 |
usd |
null |
| 2023-01-19 |
2 |
null |
gbp |
If we want to reduce those rows to 1 per Date, id we need a GROUP BY. And a GROUP BY requires that we have an aggregation function for all fields that are not listed in GROUP BY list (Date and Id). MAX() and MIN() are aggregation functions that we could use on a string type and the aggregation wouldn't take NULL into account, just what we need. In other words, we are using MAX() or MIN() just to eliminate NULLs. Thus applying MAX() or MIN() and GROUP BY:
select [date], id,
MIN(case when [type]='comm' then currency end) as Comm_cur,
MIN(case when [type]='exch' then currency end) as Exch_cur
from myTable
group by [date], id;
results:
| date |
id |
Comm_cur |
Exch_cur |
| 2023-01-12 |
1 |
usd |
usd |
| 2023-01-19 |
2 |
usd |
gbp |
DBfiddle demo
id=2records in your output table?