Joining multiple instances of same table?
Suppose I have an
items
table where each item can have up to 3 tags
. This is hardcoded - the items table has columns tag1id
tag2id
and tag3id
. I want to find all items that have a given tag. The code below seems to select the proper items but I do not get the tag2
or tag3
properties on the result. Is there something I'm doing wrong, and more generally, is there a better way to achieve this?
6 Replies
You are doing it right, the problems is data aggregation
You are probably getting an array of type:
But since you are left joining, whenever tag1 is string the other 2 tags will be null
Have you tried using
innerJoin(...)
instead of leftJoin()
?Trying that gives the same results. The following query yields the correct results. My guess is there is something going on with the aliasing.
The alias feature isn't well documented and doesn't seem to be used much, which makes me think I'm using a weird pattern for a fairly common thing. I hardcoded the 3 tag limit thinking it would make things easier or have performance benefits, but maybe a standard
items_tags
join table would make more sense even with that given constraint?If you pass
{logger: true}
to the drizzle function during instantiation, you'll get your queries logged to the console. I'm pretty sure the printed query will be exactly what you'd expect
That would rule out any issue with the alias
If you had the relations defined you could use the Relational Query API and it would do the data aggregation for youOk, using the logger, it seems that the column names are not being aliased (e.g.
select ... t1.name, t2.name ...
) so only the last one returns. I guess I might have expected them to be aliased with the property names passed to the select function (e.g. select ... t1.name as tag1
), but it appears that mapping happens later. Is there any way to specify that behavior? edit - I was able get it working with sql`${t1.name} as abc`
- is this recommended or is there a better way?
I have the relations defined and I tried that way first but I was unsure how to reference the aliased tables in the where clause:
Is there any way to specify that behavior?One way is how you did it and another is See if this works for the RQB:
With that, it selects all items but only adds the tag data when it matches. So if
tag2.name == 'test'
, then tag1
and tag3
will be null in the results even if they have values. I think this is the issue I was running into - the tag1 or tag2 or tag3
logic needs to be applied "at the top level," which seems outside the scope of the RQB?
What do you think of the idea to switch it to a many-to-many join table (items_tags
)? That should make this query fit better with the RQB, which I would like to use wherever possible. It's just adding another table which seems like it would be less performant but that might not be a necessary optimization right now.
Either way I do at least have a workable solution for now and I thank you for your time helping me with this!
One other idea would be to use the tag name as the primary key and avoid any joins, I'm just worried that could create problems down the road