PostgreSQL выберите заявление - PullRequest
2 голосов
/ 25 марта 2012

С учетом следующих таблиц:

 shows:

      title      | basic_ticket_price
 ----------------+--------------------
  Inception      |              $3.50
  Romeo & Juliet |              $2.00

performance:

  perf_date  | perf_time |     title
 ------------+-----------+----------------
  2012-08-14 | 00:08:00  | Inception
  2012-08-12 | 00:12:00  | Romeo & Juliet

booking:
  ticket_no | perf_date  | perf_time | row_no | person_id
 -----------+------------+-----------+--------+-----------
          1 | 2012-08-14 | 00:08:00  | P01    | 1
          2 | 2012-08-12 | 00:12:00  | O05    | 4
          3 | 2012-08-12 | 00:12:00  | A01    | 2

И дополнительной таблицы: место, которое содержит список мест, пронумерованных так же, как в row_no при бронировании с названием области.

Сгруппировавзабронированные места с использованием этого оператора:

select count(row_no) AS row_no,
       area_name 
from seat 
where exists (select row_no 
              from   booking 
              where booking.row_no = seat.row_no) 
group by area_name;

, который производит:

    row_no |  area_name
   --------+--------------
         1 | rear stalls
         2 | front stalls

Как теперь можно использовать подсчитанные строки и имя_области для написания одного оператора SQL для создания списка, отображающего именашоу, даты и время выступлений, а также количество забронированных мест в каждой области?

Я пробовал это:

 select s.title,
        perf_date,
        perf_time,
        count(row_no) AS row_no,
        area_name 
 from shows s, 
      performance,
      seat 
 where exists (select row_no 
               from booking 
               where booking.row_no =  seat.row_no) 
 group by area_name,s.title,performance.perf_date,performance.perf_time;

Но он показывает повторяющиеся строки:

      title      | perf_date  | perf_time | row_no |  area_name
 ----------------+------------+-----------+--------+--------------
  Romeo & Juliet | 2012-08-12 | 00:12:00  |      1 | rear stalls
  Romeo & Juliet | 2012-08-14 | 00:08:00  |      2 | front stalls
  Inception      | 2012-08-12 | 00:12:00  |      1 | rear stalls
  Inception      | 2012-08-14 | 00:08:00  |      2 | front stalls
  Inception      | 2012-08-14 | 00:08:00  |      1 | rear stalls
  Inception      | 2012-08-12 | 00:12:00  |      2 | front stalls
  Romeo & Juliet | 2012-08-14 | 00:08:00  |      1 | rear stalls
  Romeo & Juliet | 2012-08-12 | 00:12:00  |      2 | front stalls
  (8 rows)

Любая помощь в решении этой проблемы будет принята.

Ответы [ 3 ]

2 голосов
/ 26 марта 2012

Вы должны рассмотреть возможность объединения столбцов perf_date date и perf_time time в один timestamp столбец:

perf_timestamp timestamp

Если вам нужен date или timeиз временной метки просто приведите его так:

SELECT perf_timestamp::time;
SELECT perf_timestamp::date;

Я бы вообще предложил использовать суррогатные первичные ключи.Название «шоу» (название фильма) не является естественным ключом - оно не уникально.Или, как уже упоминалось @user_unknown: время запуска не является практическим первичным ключом для исполнения.Для этого вы можете использовать столбцы serial .Вся установка может выглядеть примерно так:

 -- show:
CREATE TEMP TABLE show (
 show_id serial PRIMARY KEY
,title text
,basic_ticket_price money  -- or numeric
);
INSERT INTO show (title, basic_ticket_price) VALUES
 ('Inception', 3.50)
,('Romeo & Juliet', 2.00);

-- performance:
CREATE TEMP TABLE performance (
 performance_id serial PRIMARY KEY
,show_id int REFERENCES show(show_id) ON UPDATE CASCADE
,perf_start timestamp
);
INSERT INTO performance (show_id, perf_start) VALUES
 (1, '2012-08-14 00:08')
,(2, '2012-08-12 00:12');

-- seat:
CREATE TEMP TABLE seat (
 row_no text PRIMARY KEY
,area_name text
);
INSERT INTO seat (row_no, area_name) VALUES
 ('P01', 'rear stalls')
,('O05', 'front stalls')
,('A01', 'front stalls');

-- booking:
CREATE TEMP TABLE booking (
 ticket_id serial PRIMARY KEY
,performance_id int REFERENCES performance(performance_id) ON UPDATE CASCADE
,row_no text REFERENCES seat(row_no) ON UPDATE CASCADE
,person_id int -- REFERENCES ?
);
INSERT INTO booking (performance_id, row_no, person_id) VALUES
 (1, 'P01', 1)
,(2, 'O05', 4)
,(2, 'A01', 2);

Тогда ваш запрос может выглядеть так:

SELECT p.perf_start
      ,sh.title
      ,s.area_name
      ,count(*) booked
FROM   booking     b
JOIN   seat        s USING (row_no)
JOIN   performance p USING (performance_id)
JOIN   show        sh USING (show_id)
GROUP  BY 1,2,3
ORDER  BY 1,2,3;

Результат:

 perf_start          | title          | area_name    | booked
---------------------+----------------+--------------+-------
 2012-08-12 00:12:00 | Romeo & Juliet | front stalls | 2
 2012-08-14 00:08:00 | Inception      | rear stalls  | 1
0 голосов
/ 25 марта 2012

На каждой записи производительности найти все заказы.Из этих бронирований, ссылку на таблицу мест, чтобы определить название области.Затем простой COUNT (*), сгруппированный по критериям для шоу / области.

SELECT
      p.perf_date,
      p.perf_time,
      p.title,
      s.area_name,
      COUNT(*) as SeatsSold
   from
      performance p

         JOIN booking b
            ON p.perf_date = b.perf_date
            AND p.perf_time = b.perf_time

            JOIN seat s
               ON b.row_no = s.row_no
   group by
      p.perf_date,
      p.perf_time,
      p.title,
      s.area_name
0 голосов
/ 25 марта 2012

Ваши строки не повторяются. Обратите внимание на различия в date и area_name в ваших результатах. Все это выглядит прекрасно для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...