I want to represents a team in my Postgres database. These teams have always 3 members. Each member have a slot, 1 for leader, and 2 and 3 for member (also useful to display the members in the good order) Each member have a level but for this team only (A character can appear in different team with a different level.
Though, one of my features, I want to select all teams that has a different composition which means, a different leader and members. (teams with member A, B and C are considered as the same as A, C and B but are different from team with C, A and B)
In another feature, I want to select all teams that contains the exact same composition.
For now, I have 3 tables,
CREATE TABLE teams (
"teamID" integer NOT NULL,
"remainingTime" double precision NOT NULL,
"desc" text NOT NULL,
difficulty character varying NOT NULL
);
CREATE TABLE public.team_member (
"teamID" smallint NOT NULL,
"charID" smallint NOT NULL,
"level" smallint NOT NULL, /*can be from 1 to 5*/
"slot" smallint DEFAULT 1 NOT NULL /*1, 2 or 3*/
);
CREATE TABLE public."character" (
"charID" integer NOT NULL,
name character varying NOT NULL,
/* others attribute */
);
My question, is now, what would be the best way to write a query that corresponds to my features, i.e. one for different teams and another for teams with the same composition ?
I guess I could create an array for each team representing the ID of its members and then compare them, but wouldn't that cause problems in terms of performance with a lot of teams ?
Is there, maybe, a more optimised model for this case ?
I thought of creating a sort of table storing the ID of its 3 members in one line and then create another table team_variation that store the level of the 3 members, and the related desc and time, but I don't know if that's really a good idea
final note, I use this database on a Javascript server so I can, if necessary, process the data received by a query that would have done a part of what I want
I propose this relational design:
fiddle
The combination of
NOT NULL,CHECK,UNIQUE,PRIMARY KEY, andFOREIGN KEYconstraints enforces your model. You can still enter incomplete teams (not all slots filled), allowing for intermediary states. But those are excluded in my queries below.There is good reason for the mix of constraints and indexes for table
team_member. See:I kept your choice of
smallint, but made the PKs of tablesteamandpersonmatch. Don't introduce a type mismatch here. I even kept the minimal payload size ofteam_memberrows at 8 bytes (maybe that's what you were optimizing for?) But unless you have good reasons, plus can reliably rule out overflow, useinteger(or evenbigint) instead. Less error prone. Adds only little cost.Note the data type
"char"for cheap enumeration. (Optional.) Not to be confused withcharorvarchar! See:Use a date/time data type for date/time data (column
remaining_time). Notfloat.Don't mix singular and plural forms for table names without good reason.
Use legal, lower-case, unquoted identifiers. In particular, avoid reserved words. See:
Queries
Already somewhat optimized for performance.
Distinct teams
Full list of distinct teams. Pick team with smallest ID from set of dupes. Exclude incomplete teams.
See:
Same teams
Select same teams as given team
(1, 2, 3)-1being the lead. Again, exclude incomplete teams.fiddle