Hi everyone, I need a bit of help. I have a couple...
# sql
b
Hi everyone, I need a bit of help. I have a couple tables ('characters', 'locations' etc) that store documents. I'm trying to create a timeline that allows people to add instances of a document to the timeline. For this I figured I'd create a 'document_instances' table to join an instance in a timeline to the document itself. The issue is that because I have multiple tables, I end up needing to construct a join based on the table name in a column. So you can see that document_id is the row I need to join and document_type is the table that the row resides in. Now I've heard this is a bad idea, but I don't really know how else to construct this functionality without this document_instance table.
m
Are you doing this so that you can track the history or changes to a document? If so, I do not understand why you need multiple tables. Why not have just one table like this: updated_at (Date of the change in doc), doc_id, user_id, doc_type, doc_contents, etc. This way you can add a new row if a doc is created, a doc is updated, or deleted. And when you query all rows with one particular doc_id and order it by the date, you would get a history of all changes to it from creation to deletion. This obviously assumes that that is what you are trying to do. I could be misunderstanding this.
b
It's a journal that has different types of documents, like a character document, location document etc. And I'm constructing a timeline document that allows you to put documents into an ordered timeline (ordered by the user, not by date). Documents might be referenced in multiple timeline documents, or multiple times in the same document.
So my idea is to have a 'document instance' table that references the timeline document plus the referenced document. The issue is that my documents are split up into different tables, so I can't join them.
One idea is to just put all the documents into one table
Or use a column in the document instance table to refer to the table that the referenced document resides, and use that for the join
But apparently that is an anti-pattern
m
Regardless of how you are ordering the documents, both methods are valid but I personally prefer one where all documents are in one table. Unless there is an explicit purpose for it, there is no need to have multiple tables for each type of document.
b
I'm leaning towards that as well, I'll have to migrate data over
I'm currently tearing my hair out over joins, I'm a real noob at backend
For example, I thought it would be easy to combine tables together so that I could SELECT in one go. For example, ```characters ID | user_id | name | bio 1 38 Sam text locations ID | user_id | name | planet 2 27 Foo Earth JOIN result: id | user_id | name | planet | bio 1 38 Sam null text 2 27 Foo Earth null ```This way I could select all documents from the different tables that had a specific user ID. But in reality I'm getting a ton of duplicates and I don't understand SQL enough to know why.
m
You should look into "Postgres Views". They are essentially a way to use complex queries again and again. So, for instance, if you had a VERY complex query with several joins, you would write it once and then create a "view" for it. Lets say you call that view "complex_query". Once that is done, you would only have to do this:
SELECT * FROM complext_query;
any time you want to run that complex query. This is only a convenience thing that you might find easy to use. As for the problem about duplicates, it is likely that you are using the wrong kind of
JOIN
. There are five or six kinds of joins in total i think.
b
Thanks for the tip about postgres views
Look at this...And notice the Venn Diagrams. They should show you why you are getting duplicates.
b
Hmm, the link doesn't work for me
b
I've tried inner joins, full outer joins, and left joins
m
How about this
b
that works
I guess I just don't understand the concept of matching
But it doesn't seem like any of the joins do what I want based on the article
I think I need sleep, I appreciate the help though
m
no worries
b
Hey just wanted to let you know I solved the issue (i think). My problem was that a join was the wrong idea because I don't have a related/common column. Using a union gets me the right result, although it's a pita to specify each column manually.
Copy code
SELECT other_id as id, user_id, campaign_id, title, null as world FROM public.other
UNION
SELECT location_id, user_id, campaign_id, name, world FROM public.locations
Is there a way to have postgres automatically detect common columns or is doing it manually the only option?
m
I think you dont have a choice but to specify each column like this
b
Thats interesting, I imagine for large datasets with many columns and queries it could get unmanageable
I figured that I should have a table for each document instead of combining them because I thought I should model my schema off the data rather than how I access it - I wonder if that's the wrong approach. Is there a good resource for learning the philosophy behind database design?
m
I am not a pro in this myself. I started using Supabase/postgres only a month or so back and as I am in the development stage, my schema keeps changing depending on what I need to do and what works for me best. Now I was in a similar position a week or so back when I couldnt decide between having two tables and joining them OR having one bigger table. As I was and still am a noob, I decided to go with the EASY TO IMPLEMENT approach both in Supabase as well as in my front end. if you are in the dev stage, then you do not need to have a solid schema right from the start. Once you develop and work on it, you will find and end up on the sweet spot that works best for you. Try this UNION method and then try a single and bigger table. See what works best for you.
b
Thanks for the help 🙂