K
Kysely•2w ago
Raizel

Joining multiple separate CTE's

I am working on a complex query. I can get it to run efficiently using multiple CTE's(Atleast in RAW SQL) but I want to port all this over to Kysely due to the typesafety. What I want is something like this: const cteOne = kyselyDb .with('myCTE', (qb) => qb .selectFrom('InboxFeedItem') .limit(10) .selectAll() ) .as('cteOne'), const cteTwo = kyselyDb .with('otherCTE', (qb) => qb.selectFrom('InboxFeedItem').offset(10).limit(10).selectAll(), ) .selectFrom('otherCTE') .select('id as xId') .as('cteTwo') I could have a number of different CTE's (possibly returned from function calls) And I want to then JOIN them OR UNION them etc. but right now its not letting me. Maybe I don't know the syntax or is it not possible ? TYIA
Solution:
conditionally added CTEs are not supported - too much type complexity involved. you could union with a subquery conditionally tho, as the result shape is already established, and union can be added to existing builder instances, outside of chain (but also with $call)....
Jump to solution
8 Replies
Igal (mobile)
Igal (mobile)•2w ago
Hey 👋 Can you share the SQL you're going after?
Raizel
RaizelOP•2w ago
This is a part of it: WITH Y AS ( SELECT i.id as ifiId, c.id as convId FROM public."InboxFeedItem"i inner join "Conversation" c on i."conversationId" = c.id inner join "ConversationOwner"co on c."conversationOwnerId" = co.id where co."instagramAccountId"= '3b133c07-4210-4cca-b85a-a9ef08b632cd' order by i."previewTimestamp" desc limit 10 ), Z AS ( SELECT * FROM Y inner join "Message" mmsg on Y.convId = mmsg."conversationId" inner join "Content" content on mmsg."originContentId" = content.id where content."platformContentId"='17969804336852591' ), REPLIED_TO_POST_OR_STORY AS ( SELECT i.id as xId FROM "InboxFeedItem" i inner join "Conversation" c on i."conversationId" = c.id inner join "CommunityMember" participant on c."participantId" = participant.id left join "CommentOwner" co on participant.id = co."communityMemberId" left join "Comment" on co.id = "Comment"."authorId" left join "Content" content on "Comment"."contentId" = content.id where content."platformContentId"='17969804336852591' ) SELECT ifiId FROM Z UNION SELECT xId from REPLIED_TO_POST_OR_STORY; I know I can chain .with in Kysely as well but I can't do that as sometimes I would conditionally need to create a CTE as well
Solution
Igal
Igal•2w ago
conditionally added CTEs are not supported - too much type complexity involved. you could union with a subquery conditionally tho, as the result shape is already established, and union can be added to existing builder instances, outside of chain (but also with $call).
Raizel
RaizelOP•2w ago
thanks! I assume the type complexity problem would also be there then for conditional joins as well ?
Igal
Igal•2w ago
Yeah Highly recommended to avoid these patterns if possible.
Raizel
RaizelOP•2w ago
ohh okay, got it the recommendation then as I see, is to use union or the $call operator in such a scenario
Igal
Igal•2w ago
.$call((db) => db.union(subquery)) OR query = query.union(subquery) is a matter of taste.
Raizel
RaizelOP•2w ago
Thank you so much!

Did you find this page helpful?