2012-03-25 2 views
2

Учитывая в следующих таблицах:PostgreSQL оператор выбора

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 

Как я могу теперь использовать подсчитанные строки и AREA_NAME написать один оператор 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) 

Любая помощь с решением этого будут оценены.

+0

Кроме того: вы упускаете условие соединения в вашей второй заявление. Это приведет к объединению карт между шоу, представлением и местом. Вы должны переписать это, используя 'JOIN ...' –

+0

, пожалуйста, примите мои извинения, я использую psql, но пометил его также как mysql, так как большинство операторов было похоже на аналогичные выражения. –

+0

Вы должны использовать серийный номер в качестве первичного ключа. Что делать, если вы получаете вторую комнату для показа фильмов?Вы не можете позволить двум фильмам одновременно, потому что они идентифицированы perf_date и perf_time. Или что делать, когда запланировано выполнение? Вы должны изменить несколько таблиц, что плохо. И небольшое предложение: я бы не стал повторять заголовок таблицы в именах столбцов. Иначе вы закончите с perf.perf_title - perf.title будет достаточно хорошим. –

ответ

0

На каждую запись, найдите все заказы. Из этих заказов связывайтесь с таблицей мест, чтобы определить название области. Затем, просто 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

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

2

Вы должны рассмотреть возможность объединения столбцов 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