If you know the values that could appear in TEST_TYPE column - you could use PIVOT statement:
WITH -- Sample Data
tbl AS
( Select '0001' "TEST_ID", '0001' "USER_ID", 'TestA01' "TEST_TYPE", '+' "A_RESULT", To_Date('03-AUG-17', 'dd-MON-yy') "TEST_DATE" From Dual Union All
Select '0001', '0001', 'TestA01', '+', To_Date('11-MAR-23', 'dd-MON-yy') From Dual Union All
Select '0002', '0001', 'TestA02', '-', To_Date('11-MAR-23', 'dd-MON-yy') From Dual Union All
Select '0003', '0001', 'TestB08', '-', To_Date('11-MAR-23', 'dd-MON-yy') From Dual Union All
Select '0004', '0001', 'TestB17', '+', To_Date('11-MAR-23', 'dd-MON-yy') From Dual Union All
Select '0005', '0002', 'TestA01', '+', To_Date('11-MAR-23', 'dd-MON-yy') From Dual Union All
Select '0006', '0002', 'TestB08', '+', To_Date('11-MAR-23', 'dd-MON-yy') From Dual Union All
Select '0007', '0003', 'TestA02', '-', To_Date('11-MAR-23', 'dd-MON-yy') From Dual
)
-- M a i n S Q L :
Select USER_ID "ANIMAL_ID", Nvl(Max(A01), 'U') "A01", Nvl(Max(A02), 'U') "A02", Nvl(Max(B08), 'U') "B08", Nvl(Max(B17), 'U') "B17"
From ( Select *
From tbl
) PIVOT( Max(A_RESULT) FOR TEST_TYPE IN('TestA01' as A01, 'TestA02' as A02, 'TestB08' as B08, 'TestB17' as B17) )
Group By USER_ID
Order By USER_ID
--
-- R e s u l t :
-- AnimalID A01 A02 B08 B17
-- -------- --- --- --- ---
-- 0001 + - - +
-- 0002 + U U +
-- 0003 U - U U
And if you want just latest test date then resulting dataset is a bit different:
Select USER_ID "ANIMAL_ID", Nvl(Max(A01), 'U') "A01", Nvl(Max(A02), 'U') "A02", Nvl(Max(B08), 'U') "B08", Nvl(Max(B17), 'U') "B17"
From ( Select *
From tbl
Where TEST_DATE = (Select Max(TEST_DATE) From tbl)
) PIVOT( Max(A_RESULT) FOR TEST_TYPE IN('TestA01' as A01, 'TestA02' as A02, 'TestB08' as B08, 'TestB17' as B17) )
Group By USER_ID
Order By USER_ID
--
-- R e s u l t :
-- AnimalID A01 A02 B08 B17
-- -------- --- --- --- ---
-- 0001 + - - +
-- 0002 + U + U
-- 0003 U - U U