Datenbankdesign: Mehrere identische Tabellen teilen, gut oder schlecht?

7

Ich bin sehr neu in SQL und Datenbanken im Allgemeinen. Ich benutze sie nur für gelegentliche Hausaufgaben, deshalb habe ich nicht einmal versucht, sie zu meistern.

Ich habe Sitzplätze in einem Theater, die Sitzplätze sind in 4 Hauptbereiche unterteilt (A, B, C, D). Jeder Bereich hat die gleiche Anzahl von Reihen und die gleiche Anzahl von Sitzplätzen pro Reihe.

In meiner Datenbank möchte ich Row + SeatNumber als zusammengesetzten Primärschlüssel und eine Tabelle für jeden Bereich haben.

Jetzt weiß ich noch nicht, wie ich meine Auswahl treffen werde, aber was ich fragen möchte: Wenn ich es so mache, sind meine Auswahl dann machbar? Ich möchte zum Beispiel eine genaue Position innerhalb des Theaters auswählen (wo ich den Bereich, die Reihe und die Sitznummer kenne).

Wären die 4 Tische ein Hindernis? Können Sie ein Beispiel geben, wie eine solche "Auswahl" aussehen könnte?

PS Dies ist mein erstes Mal auf der Site. Wenn die Frage nicht hierher gehört, leiten Sie mich bitte zu einer geeigneteren Site innerhalb des Stapelaustauschs.

Kalec
quelle
2
Es ist besser, wenn Sie eine einzelne Tabelle mit dem Bereich als weitere Spalte haben.
Philᵀᴹ
Ich brauche Sitznummer und Reihe (in Kombination mit Fläche), um eindeutig zu sein. Dies wäre mit PK (Reihe & Sitz) in verschiedenen Bereichen (Tabellen) einfach. Aber wie kann ich das sonst tun? Gibt es EINZIGARTIG (Bereich, Sitzreihe), das die Kombination von 3 einzigartig macht (nicht jede Spalte einzeln)?
Kalec
Verwenden Sie eine eindeutige Einschränkung
Philᵀᴹ

Antworten:

18

Sie sollten hierfür eine Tabelle verwenden, es sei denn, Sie benötigen strengere Einschränkungen.

Jeder Bereich hat die gleiche Anzahl von Reihen und die gleiche Anzahl von Sitzplätzen pro Reihe.

Angenommen, es gibt 5 Reihen in jedem Bereich und 6 Sitzplätze in jeder Reihe. Sie möchten etwas in diese Richtung verwenden.

create table seats (
  area char(1) not null check (area in ('A', 'B', 'C', 'D')),
  row integer not null check ( row between 1 and 5 ),
  seat integer not null check ( seat between 1 and 6 ),
  primary key (area, row, seat)
);

Um einen einzelnen Sitzplatz auszuwählen, geben Sie drei Werte in die WHERE-Klausel ein.

select *
from seats
where area = 'A' and
       row =  1   and
      seat =  2;

Um einen Tisch wie diesen zum Modellieren von Sitzplatzreservierungen zu verwenden, füllen Sie ihn mit allen möglichen Bereichen, Reihen und Sitzplätzen. Stellen Sie dann einen Fremdschlüsselverweis darauf ein.

create table reservations (
  performance_time datetime not null,
  party_name varchar(40) not null,
  area char(1) not null,
  row integer not null,
  seat integer not null,
  primary key (performance_time, party_name, area, row, seat),
  foreign key (area, row, seat) references seats (area, row, seat)
);

Mit dieser Abfrage können Sie alle Sitzplätze für eine Aufführung anzeigen.

select s.area, s.row, s.seat, r.performance_time, r.party_name
from seats s
left join reservations r
       on r.area = s.area and
          r.row  = s.row  and
          r.seat = s.seat and
          r.performance_time = '2013-04-30 08:00 pm'

Und Sie können alle verfügbaren Plätze für eine Aufführung mit etwas in dieser Richtung bekommen.

with seating as (
  select s.area, s.row, s.seat, r.performance_time, r.party_name
  from seats s
  left join reservations r
         on r.area = s.area and
            r.row  = s.row  and
            r.seat = s.seat and
            r.performance_time = '2013-04-30 08:00 pm'
)
select *
from seating
where performance_time is null

Standardmäßig erstellt SQL Server einen Clustered-Index für eine Primärschlüsseleinschränkung. Sie sollten die Reihenfolge der Spalten in Ihren Primärschlüsseleinschränkungen sorgfältig prüfen und auch andere Indizes hinzufügen. (Zumal Ihre Ausgänge häufig nach Fläche, Reihe und Sitz geordnet werden müssen.)

Mike Sherrill 'Cat Recall'
quelle
Vielen Dank für eine so ausführliche Antwort. Ich hatte etwas in der Zeile "Verwenden Sie eine eindeutige Einschränkung" erwartet (habe gerade herausgefunden, dass es auch für Kombinationen von zwei oder mehr Spalten funktioniert).
Kalec
Hohe Qualität und gut durchdachte Antwort. Wünschte, mehr Leute antworteten auf diese Qualität.
DeepSpace101
2
Danke, Sid. Ich hoffe, Sie wissen, dass ich Sie in meinem Lebenslauf zitieren werde.
Mike Sherrill 'Cat Recall'
Sehr schöne Antwort :)
Christiandev
1
Ja, mehr Tabellen für mehr referenzielle Integrität. (Aber es gibt keine "Bereiche" -Tabelle. Es könnte jedoch eine geben.) Normalerweise vertrauen Sie den lokalen Administratoren bis zu einem gewissen Grad. Sie haben ein begründetes Interesse daran, vorsichtig zu sein. Personen, die telefonische Reservierungen vornehmen, hätten keine Berechtigungen zum Einfügen oder Aktualisieren von "Sitzplätzen".
Mike Sherrill 'Cat Recall'
7

Wenn die Informationen für die Sitzeinheit pro Bereich gleich sind, können Sie das Design vereinfachen, indem Sie nur eine SeatsTabelle mit einer AreaSpalte haben.

In diesem Fall würde die Abfrage ungefähr so ​​aussehen:

SELECT ... FROM Seats 
WHERE Seats.Area = 'A' 
AND Seats.Row = X 
AND Seats.Number = Y;

Sie könnten je nach finden , was dem Datenzugriff und UI - Technologie , die Sie verwenden , dass mit einem Surrogat Primärschlüssel arbeitet , ist einfacher, und nur eine eindeutige Einschränkung auf der hinzufügen Area, Rowund NumberKombination.


quelle
Ja ich sehe. Das wäre in der Tat viel besser und viel einfacher. Vielen Dank. Obwohl ich fragen muss: Einzigartig für 3 Spalten, bedeutet das, dass die Kombination der drei einzigartig ist, nicht jede einzeln?
Kalec
3
@ Kalec Ja, die Kombination ist einzigartig. Wenn sie einzeln einzigartig wären, könnten Sie nicht mehr als einen Sitzplatz pro Bereich haben!
Branko Dimitrijevic
6

Warum haben Sie nicht einfach eine Bereichstabelle und fügen die ID als FK zur Haupttabelle hinzu? Auf diese Weise müssen Sie keine komplexen Abfragen schreiben. Wenn ein weiterer Bereich hinzugefügt wurde, müssen Sie der Bereichstabelle nur einen Datensatz hinzufügen und keine neue Tabelle.

CREATE TABLE #seats
    (
      Id INT ,
      SeatRow INT ,
      SeatNumber INT ,
      AreaId INT
    )

CREATE TABLE #areas ( Id INT, AreaName VARCHAR(50))

Diese Art von Idee und Sie können die referenzielle Integrität erzwingen, wenn Sie einen Bereich nur hinzufügen können, wenn er in der Bereichstabelle http://en.wikipedia.org/wiki/Referential_integrity vorhanden ist

christiandev
quelle
4

Es lohnt sich wirklich, über die Arten von Abfragen nachzudenken, die Sie über Ihre Daten ausführen möchten, und über die Struktur des Restes Ihrer Datenbank - das wird Ihnen mit ziemlicher Sicherheit helfen, das Modell zu überdenken.

Zum Beispiel möchten Sie wahrscheinlich Ihre Plätze mit Tickets verknüpfen, wenn Sie einen Platz für eine Aufführung verkaufen. Das bedeutet, dass Sie eine Tabelle mit dem Namen "Leistung" und eine andere Tabelle mit dem Namen "Ticket" haben. Betrachten Sie die Struktur von "Ticket" - Sie möchten es mit dem Sitzplatz verknüpfen. In Ihrem aktuellen Design ist der Fremdschlüssel von "Ticket" zu "Sitzplatz" hässlich - Sie benötigen vier Spalten, um dies zu speichern, und Sie können nicht garantieren, dass das Ticket keine Links zu zwei Sitzplätzen enthält, wenn ein Fehler vorliegt irgendwo.

Dies legt nahe, dass die Vorschläge von devdigital und christiandev wahrscheinlich nützlicher sind.

Sie möchten wahrscheinlich auch herausfinden, wie viele freie Plätze Sie für eine Aufführung haben. Auch hier müsste Ihr aktuelles Design 4 Tabellen abfragen, während die Alternative nur eine einzige Abfrage erfordert.

Wenn Sie jemals die Art und Weise ändern möchten, wie Sie "Sitze" strukturieren - beispielsweise durch Hinzufügen einer Spalte "Standardpreis" -, müssen Sie diese Änderung in Ihrem aktuellen Design an vier Stellen vornehmen. Wenn Sie eine einzelne Tabelle mit einem Fremdschlüssel "Bereich" verwenden, können Sie diese Änderung nur einmal vornehmen.

Neville Kuyt
quelle
Vielen Dank für Ihre Antwort. Ich stimme Ihnen von ganzem Herzen zu. Mein Hauptproblem war, dass ich keine Ahnung hatte, wie die Tabelle funktionieren sollte, weil ich wollte, dass Reihe + Sitz + Bereich eine eindeutige Kennung ist (ich sah es nur als Primärschlüssel), aber der Bereich musste wiederholt werden. Wenn ich wüsste, dass ich die Kombination der drei einzigartig machen kann, würde ich die Frage nicht einmal stellen, aber weil ich so neu in dieser Sache bin, "einfach" einfach nicht "vorbeischauen".
Kalec
3

Es ist besser, nur eine Tabelle mit einer Bereichsspalte zu behalten

TheEwook
quelle