MySQL присоединяется или подзапрос - PullRequest
1 голос
/ 10 июля 2011

У меня есть три таблицы: шоу, эпизод и проветривание. Каждое шоу имеет несколько эпизодов, и каждый эпизод имеет несколько передач. Я хочу одну строку для каждого шоу, где airing.start_time является ближайшим start_time прямо сейчас (но в будущем) Если нет будущего start_time, тогда я все равно хочу строку (start_time должно быть пустым).

Вот мой текущий запрос:

    SELECT s.project_id,
           s.title, 
           s.description, 
           s.topic, 
           s.status, 
           a.start_time, 
           a.channel 
      FROM show s 
 LEFT JOIN episode e ON s.project_id = e.project_id 
 LEFT JOIN airing a ON e.episode_id = a.episode_id 
     WHERE s.status = "Active" AND s.title LIKE "a%" AND a.start_time > NOW()
  ORDER BY s.title ASC, a.start_time ASC
  GROUP BY s.project_id

Я не уверен, куда идти дальше. Любая помощь?

Ответы [ 4 ]

2 голосов
/ 10 июля 2011

Без отображения airing.channel:

    SELECT s.project_id,
           s.title, 
           s.description, 
           s.topic, 
           s.status, 
           MIN(a.start_time) 
      FROM show s 
 LEFT JOIN episode e ON s.project_id = e.project_id 
 LEFT JOIN airing a ON e.episode_id = a.episode_id 
                    AND a.start_time > NOW()
     WHERE s.status = "Active" AND s.title LIKE "a%"
  GROUP BY s.project_id
  ORDER BY s.title ASC

Отображение channel тоже:

    SELECT s.project_id,
           s.title, 
           s.description, 
           s.topic, 
           s.status, 
             ( SELECT a.start_time
                 FROM airing AS a 
                 JOIN episode AS e ON e.episode_id = a.episode_id 
                WHERE s.project_id = e.project_id 
                  AND a.start_time > NOW() 
             ORDER BY a.start_time
                LIMIT 1    
             )
           AS start_time,
             ( SELECT a.channel
                 FROM airing AS a 
                 JOIN episode AS e ON e.episode_id = a.episode_id 
                WHERE s.project_id = e.project_id 
                  AND a.start_time > NOW() 
             ORDER BY a.start_time
                LIMIT 1    
             )
           AS channel
      FROM show s     
     WHERE s.status = "Active" AND s.title LIKE "a%"
  ORDER BY s.title ASC

или:

    SELECT s.project_id,
           s.title, 
           s.description, 
           s.topic, 
           s.status, 
           a.start_time,
           a.channel   
      FROM show s     
 LEFT JOIN airing a ON a.airing_id =
                     ( SELECT a.airing_id
                         FROM airing AS a 
                         JOIN episode AS e ON e.episode_id = a.episode_id 
                        WHERE s.project_id = e.project_id 
                          AND a.start_time > NOW() 
                     ORDER BY a.start_time
                        LIMIT 1    
                     )   
     WHERE s.status = "Active" AND s.title LIKE "a%"
  ORDER BY s.title ASC

Если они медленные, сообщитенам, какие у вас индексы для таблиц и какие типы полей.

1 голос
/ 10 июля 2011

Этот запрос звучит так, как вы хотите, но канал также будет нулевым, если нет будущего start_time

SELECT s.project_id,
       s.title, 
       s.description, 
       s.topic, 
       s.status, 
       a.start_time, 
       a.channel 
FROM show s 
LEFT JOIN episode e ON s.project_id = e.project_id 
LEFT JOIN (SELECT start_time, channel, episode_id FROM airing a1
           WHERE a1.start_time = (SELECT MIN(a2.start_time) FROM airing a2
                                  WHERE a2.start_time > NOW() AND
                                        a2.airing_id = a1.airing_id)
          ) a ON e.episode_id = a.episode_id 
WHERE s.status = 'Active' AND s.title LIKE 'a%'
ORDER BY s.title ASC, a.start_time ASC
GROUP BY s.project_id

Редактировать согласно комментарию ypercube:

SELECT s.project_id,
       s.title, 
       s.description, 
       s.topic, 
       s.status, 
       a.start_time, 
       a.channel 
FROM show s 
LEFT JOIN (SELECT a1.start_time, a1.channel, e.project_id
           FROM airing a1
                JOIN episode e ON a1.episode_id = e.episode_id
           WHERE a1.start_time = (SELECT MIN(a2.start_time) FROM airing a2
                                  WHERE a2.start_time > NOW() AND
                                        a2.airing_id = a1.airing_id)
          ) a ON s.project_id = a.project_id 
WHERE s.status = 'Active' AND s.title LIKE 'a%'
ORDER BY s.title ASC, a.start_time ASC
GROUP BY s.project_id
1 голос
/ 10 июля 2011

Чтобы справиться с отсутствующим временем начала, измените проверку времени на

... AND ((a.start_time > NOW()) or (a.start_time is null))

при условии, что упомянутое вами "пустое" значение равно нулю. Однако, если вы не очистите start_times для предыдущих эпизодов, это не сработает, и вы должны просто полностью удалить проверку start_time. Нет смысла проверять время last_start, потому что вы выполняете (x> y или x <y), что приведет к ошибке, только если (x = y).

0 голосов
/ 10 июля 2011

Попробуйте это:

SELECT s.project_id,
       s.title, 
       s.description, 
       s.topic, 
       s.status, 
       a.start_time, 
       a.channel 
FROM show s 
LEFT JOIN episode e ON s.project_id = e.project_id 
LEFT JOIN airing a ON e.episode_id = a.episode_id 
WHERE s.status = "Active" AND s.title LIKE "a%" AND a.start_time > NOW()
-- Here's the new bit:
AND a.start_time = (SELECT start_time from airing where episode_id = e.episode_id order by abs(now() - start_time) limit 1)
ORDER BY s.title ASC, a.start_time ASC
GROUP BY s.project_id

Это выбирает проветривание, наиболее близкое к «сейчас», выполняя предварительный отбор по расстоянию во времени от предела 1 от настоящего времени (чтобы выбрать самый низкий дифференциал)

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