2

私はPostgreSQLを使用しています。私はこの次のスキーマを持っています:

CREATE TABLE users (
  id int PRIMARY KEY
);

CREATE TABLE trips (
  id int PRIMARY KEY,
  driver_id int,
  FOREIGN KEY driver_id REFERENCES users(id)
);

CREATE TABLE trip_passengers (
  id int PRIMARY KEY,
  user_id int,
  trip_id int,
  FOREIGN KEY trip_id REFERENCES trips(id)
  FOREIGN KEY user_id REFERENCES users(id)
);

CREATE TABLE feedbacks (
  id int PRIMARY KEY,
  trip_id int,
  rater_id int,
  ratee_id int,
  review TEXT,
  FOREIGN KEY trip_id REFERENCE trips(id),
  FOREIGN KEY rater_id REFERENCES users(id),
  FOREIGN KEY ratee_id REFERENCES users(id),
  UNIQUE (trip_id, rater_id, ratee_id)
);

以下のルールがあります。

  • トリップには複数の乗客を含めることができます (trip_passengers テーブルを使用)。
  • ユーザーは一緒に旅行した場合にのみレビューを作成できます。
  • ドライバーは乗客にレビューを投稿できます。
  • 乗客はドライバーにレビューを投稿することもできます。
  • 乗客は乗客にレビューを書くことができます。

ケース:

表:ユーザー

| id  | username   |
|-----+------------+
| 1   | driver     |
| 2   | passenger1 |
| 3   | passenger2 |

表:旅行

| id  | driver_id |
|-----+-----------+
| 1   | 1         |

表: trip_passengers

| id  | trip_id | user_id |
|-----+---------+---------+
| 1   | 1       | 2       |
| 2   | 1       | 3       |

まだ確認していない、乗客 1 を持つドライバーからのすべての旅行を取得したいとします。これは trip#1 を返します。

ドライバーが乗客 1 にレビューを行い、クエリを再度実行すると、何も返されません。

乗客の場合も同じです。まだ確認していない乗客 2 を持つ乗客 1 のすべての旅行を取得したい場合、両方が同じ旅行に乗るため、旅行 #1 を取得します。

特定のユーザーからまだレビューしていない別のユーザーへのすべての旅行を戻すにはどうすればよいですか?

これが私の最後の試みですが、いくつかのケースは満たされていません。

SELECT trips.* FROM trips
  INNER JOIN trip_passengers AS t1 ON t1.trip_id = trips.id
  INNER JOIN trip_passengers AS t2 ON t1.passenger_id = :rater_id AND
    t2.passenger_id = :ratee_id AND t1.trip_id = t2.trip_id
  LEFT JOIN feedbacks ON feedbacks.trip_id = trips.id AND
    feedbacks.rater_id = t1.passenger_id
  WHERE feedbacks.review IS NULL
4

3 に答える 3

2

この設計では、要件は適用されません。レビュー担当者またはレビュー対象者が旅行に参加したかどうかに関係なく、どのユーザーも他のユーザーにフィードバックを送信できます。

ここに提案があります:

ユーザー

CREATE TABLE users
( user_id int PRIMARY KEY
) ;

旅行

CREATE TABLE trips
( trip_id int PRIMARY KEY
) ;

Trip_participants (乗客とドライバー)

CREATE TABLE trip_participants
( trip_id int,
  user_id int,
  PRIMARY KEY (trip_id, user_id),
  FOREIGN KEY trip_id REFERENCES trips (trip_id),
  FOREIGN KEY user_id REFERENCES users (user_id)
) ;

Trip_drivers

CREATE TABLE trip_drivers
( trip_id int,
  driver_id int,
  PRIMARY KEY (trip_id, driver_id),
  UNIQUE KEY (trip_id)                -- optional, to enforce that a trip
                                      -- has only one driver.
  FOREIGN KEY (trip_id, driver_id) 
    REFERENCES trip_participants (trip_id, user_id)
) ;

フィードバック

CREATE TABLE feedbacks
( feedback_id int PRIMARY KEY,
  trip_id int,
  rater_id int,
  ratee_id int,
  review TEXT,
  UNIQUE KEY (trip_id, rater_id, ratee_id) ,
  FOREIGN KEY (trip_id, rater_id) 
    REFERENCES trips(trip_id, user_id),
  FOREIGN KEY (trip_id, ratee_id) 
     REFERENCES trips(trip_id, user_id),
  CHECK (rater_id <> ratee_id)
) ;

欠けているtrip_passengersのはビューです:

Trip_passengers

CREATE VIEW trip_passengers AS
  SELECT trip_id, user_id
  FROM trip_participants
  WHERE (trip_id, user_id) NOT IN
        ( SELECT trip_id, driver_id
          FROM trip_drivers
        ) 
;

最後に、まだレビューされていないすべての旅行を返すクエリ:

SELECT t.*
FROM trips AS t
WHERE t.trip_id NOT IN
      ( SELECT trip_id 
        FROM feedbacks
      ) ;
于 2012-08-05T14:12:12.223 に答える
1

レビューされた旅行としていくつものレビューが受け入れられた場合、これでそれが可能になります。

旅行から*を選択
ここで、t.idはありません
    (SELECTdistinct(t.id)
    トリップからt、フィードバックf
    WHERE t.id = f.trip_id)

サブクエリを使用して、レビュー済みのすべての旅行を選択してから、レビュー済みの旅行に含まれていない旅行を選択します。

于 2012-08-05T13:57:49.757 に答える
1

これを試して:

SELECT  a.*
FROM    trips a
            INNER JOIN  feedbacks f
                on a.ID = b.trip_id
            LEFT JOIN trips c
                on a.ID = c.ID
WHERE   c.ID IS NULL
于 2012-08-05T14:07:47.907 に答える