I'm trying to create a table in Postgres to represent a many-to-many relationship between rows of the same table.
I have a table called outerwear (which is like jackets, etc) and I want to create a many-to-many relationship between instances of outerwear.
I'm wondering what the best way is to create a join table to model this relationship that takes into account the fact that A to B is the same as B to A. So far I have this (which is just a normal join table):
CREATE TABLE outerwear_outerwear_join (
a_outerwear_id integer REFERENCES outerwear,
b_outerwear_id integer REFERENCES outerwear,
PRIMARY KEY(a_outerwear_id, b_outerwear_id)
);
But again this does not account for the fact that flipping the order of the columns should not change the value/uniqueness of a row.
Create a UNIQUE INDEX , using least and greatest functions.
CREATE UNIQUE INDEX unq_test_a_b
ON outerwear_outerwear_join ( LEAST(a_outerwear_id, b_outerwear_id), GREATEST(
a_outerwear_id, b_outerwear_id));
Demo
Related
I'm currently designing a system where we use Postgres as the backend. In that system users can upload files, and those files can be attached to various objects, where each object has it's own table. Currently I'm using a separate join table for each object to the file table, i.e. the DB layout looks something like this:
table File
table A
table A_to_File
table B
table B_to_File
table C
table C_to_File
Each join table has two columns, one for the id of the file, one for the id of the object in the object table, and both columns are defined as foreign keys on the respective tables.
Now this results in quiet a few database tables, and I was wondering if there is an elegant solution to replace those join tables with just a single one, where the column with the foreign key is dynamic and points to either the tables A, B or C (with some hint to which object table is used in that row). So in my imagination a table that would be created this way:
CREATE TABLE object_to_file (
object_id int NOT NULL,
file_id int NOT NULL,
FOREIGN KEY (file_id) REFERENCES File(id),
FOREIGN KEY (object_id) REFERENCES (A(id) of B(id) or C(id))
)
Is this in any way possible, or in another manner? I'm basically just curious, given that the current solution works just fine.
I have a situation while database designing, A simple issue but needed a working suggestions
My database tables:
TableAees.
TableBees.
Aees can mapped/contain one or more records of table Bees or also can be without any Bees
Aees can also mapped with one or more records of table Aees itself
Here normal primary key and foreign key relationship/hierarchy won't solve the purpose and also worried that parent/child hierarchy may end up in forming a loop between tables and can give a duplicates records on various joins.
Need a better table mapping for above mentioned tables(a,b) which will satisfy 1 and 2 points.
So to avoid such a situation, how the table relationship/hierarchy will be a better approach?
Database used: SQL Server
Thanks for sharing your knowledge.
You seem to describe a many-to-many relationship. If so, you would create a thrid table to store that relationship, like so:
create table a (
a_id int primary key,
...
);
create table b (
b_id int primary key,
...
);
create table ab (
a_id int references a(a_id),
b_id int references b(b_id),
primary key (a_id, b_id)
)
Each a/b tuple is stored on a separate row in bridge table ab.
I'm currently working on a simple dummy project to refresh my knowledge on SQL and to learn a few new things :)
I have a table Article with the columns:
aID, price
I have another table Storage:
sID, aID, count
The Storage table references the aID as a foreign key and the count column say how much of an article is stored.
Now I want to add a column value to my Storage table. This column should be calculated by Article.price * Storage.count.
I found after searching the web that you can have calculated columns like this
CREATE TABLE tbl
(
int1 INT,
int2 INT,
product BIGINT GENERATED ALWAYS AS (int1 * int2) STORED
);
But I haven't found an example how to this with columns from another table.
What do I have to do in order to use the price from the referenced aID in the calculation?
You cannot define a generated column based on values from other tables. Per the documentation:
The generation expression can refer to other columns in the table, but not other generated columns. Any functions and operators used must be immutable. References to other tables are not allowed.
You can achieve the expected behavior by creating two triggers on both tables but usually creating a view based on the tables is a simpler and more efficient solution.
I am trying to build a table which will hold the 'relationship' of a parent table and a child table. However each column in both tables are no keys or unique and there are duplicate values in each.
Example
Table A - Parent (Fact)
**CartNumber**
Table B - Child
**CartNumber** not unique
CartValue
CartNumber from table A links to CartNumber in B.
I have tried to implement a foreign key with NOCHECK but of course that will not work since the child column is not a primary key or unique. Bear in mind, I am ONLY trying to define that there is a link between the two columns/tables. Is there any way to define a 'loose' relationship between the two columns? Preferably a method where I can reference the sys views or information schema to extract this information
To be honest: This design smells and - if possible - you should think about changing this...
There is no chance to define a FOREIGN KEY CONSTRAINT on non-unique columns the way you describe it.
But: To define a JOIN there is no need for a FK!
My suggestion:
Create a VIEW like this:
CREATE VIEW dbo.MyView
AS
SELECT a.Col1,a.Col2,...
,b.Col1,b.Col2,...
FROM TableA AS a
[INNER/LEFT/RIGHT/FULL OUTER] JOIN TableB AS b ON a.RelField=b.RelField;
With such a VIEW you will get the data joined on this non-unique information.
UPDATE
Taken form your comment:
the end goal is just to provide an external web service with information that says Column A from Table A is used to join onto Column B from Table B
You can create a meta-table like this:
CREATE TABLE dbo.ColumnReference
(
ColumnReferenceID INT IDENTITY
,TABLE_NAME_A VARCHAR(255) NOT NULL
,COLUMN_NAME_A VARCHAR(255) NOT NULL
,TABLE_NAME_B VARCHAR(255) NOT NULL
,COLUMN_NAME_B VARCHAR(255) NOT NULL
);
--inlcude SCHEMA if needed...
In this case you can maintain these relations in your own structure..., you might even add details, rules, what ever...
The web service will call this directly. You might use a VIEW to combine existing relations (defined as FK CONSTRAINT) with your own meta table (simply with UNION ALL).
I'm learning partitioning tables in SQL Server and I got stuck with this problem: I have 2 linked tables - parent and child. One of them (or maybe even both) is a partitioned table. When I'm implementing a partitioned view do I need to include 2 identical columns in it - the one that references parental table (from child) and the primary key that is being referenced (from parent)?
I'm having troble with it since MSDN says:
Column Rules:
All columns in each member table must be included in the select list. SELECT * FROM is acceptable syntax.
But views should make the representation of (linked) tables easier, so not all the columns should be included in view.
And in my case, according to MSDN I have to include all the columns of both tables into a view (and 2 of them would be identical). It seems to me as not very logical solution.
For example:
Database 1:
create table manufacturer
(
id int,
manufacturer_name varchar(35),
PRIMARY KEY (id),
CONSTRAINT CHK_manufacturer_id
CHECK (id < 1000)
);
create table product
(
pid int,
product_name varchar(35),
mid int,
PRIMARY KEY (pid),
CONSTRAINT CHK_product_pid
CHECK (pid < 1000),
CONSTRAINT FK_product_mid
FOREIGN KEY (mid)
REFERENCES manufacturer(id)
);
Database 2:
Same tables with CHECK constraints (id >= 1000)
View:
create view dist_view as
select *
from db1.product p1
inner join db1.manufacturer m1 on p1.mid = m1.id
UNION ALL
select *
from db2.product p2
inner join db2.manufacturer m2 on p2.mid = m2.id
So the view with look like
pid | prod_name | mid | id | manufact_name
and mid = id.
In my opinion a view like this contradicts the main advantage of using views - simple representation of tables. So I would like to have a view like this:
(pid) | prod_name | manufact_name
How do I solve this?
First, you probably should not bother learning about partitioned views. The correct way to do partitioning is using partitioned tables, rather than views.
This is repeated in the documentation. For instance:
Note
The preferred method for partitioning data local to one server is
through partitioned tables. For more information, see Partitioned
Tables and Indexes.
(And I note that your queries are all on one server.)
Second, a partitioned view is created by union all on base tables. You are using joins, so that is just a regular view.
I would suggest that you re-evaluate your data structures and think more about partitioned tables than partitioned views.