I’ve used a query to pull back multiple matches, but it’s not arrayformula friendly which makes it hard to work with and it uses a lot of sheet processing time if you have a lot of rows.
This is the formula I used to use to build dynamic html tables. I’ve since converted it to do everything within glide. The Concatenate with the Query is what joins everything together.
=IF(LEN(C10)=0, "", CONCATENATE("<table width=100%>" , query(Lessons!A$2:L, "select K where A='" & A10 & "' and E='" & B10 & "' and J>= date'" & TEXT(D10, "yyyy-mm-dd") & "' and J<= date'" & TEXT(E10, "yyyy-mm-dd") & "' order by A, D ",0), "</table></br><div style=""text-align: right"">TOTAL: ", DOLLAR(G10, 2), "</div>"))
I have to wonder though if you would have some process in your app where you would already have a Joined List column of your data, then through some action tiggered by the user, you could write that joined list to a sheet column. That would be a lot easier, in my opinion, instead of trying to do it directly in the sheet with sheet formulas.