2014-10-08 3 views
3

Я изучаю SQL и просматриваю главы приложения GalaXQL.SELECT .. FROM (SELECT .. FROM ..). Как я могу улучшить этот запрос?

Я написал следующий запрос в ответ на вопрос «Hilight the star (or stars), который имеет планету с самым высоким расстоянием на орбите в галактике. Не забудьте очистить старые hilights до начала».

Этот запрос возвращает результат starid: 23334, который при вставке в таблицу hilight позволяет мне прогрессировать. Тем не менее, программа зависает в течение долгого времени, прежде чем передать этот результат мне, поэтому я подозреваю, что гораздо эффективнее использовать эту информацию из базы данных.

Этот запрос работает, но требуется много времени для обработки, как я могу улучшить этот запрос?

INSERT INTO hilight 
SELECT DISTINCT s.starid 
FROM planets AS p, stars AS s, moons AS m 
WHERE s.starid=(SELECT starid 
       FROM planets 
       WHERE orbitdistance=(SELECT MAX(orbitdistance) 
            FROM planets)); 

Моя логика этой структуры запроса

Сначала найти планету с орбиты наибольшее расстояние от стола «планет».

Второе для сравнения значения «наивысшего расстояния орбиты» с полем «orbitdistance» таблицы «Планеты» и возврата «звездного», относящегося к этому полю.

Третий сравнить значение поля «starid» в таблице «планет» в поле «starid» в таблице «звезд», а затем вставить, что «starid» к столу «блика».

Структура данных:

enter image description here

+0

Попробуйте изменить 'SELECT DISTINCT s.starid FROM planets AS p, stars AS s, moons AS m WHERE ...' to: 'SELECT s.starid FROM stars AS s WHERE ...' –

+0

Проблема номер 1 заключается в том, что вы используете [древний синтаксис соединения.] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style-joins.aspx), а также почему вы делаете крест? Разве у вас нет условия «ВКЛ» для этих объединений? Если бы вы это сделали, вам, вероятно, тоже не понадобилось бы этого. – Zane

+0

@ypercube: Это приведет к большому количеству копий «звездного», передаваемого «hilight». Поскольку «starid» в таблице «hilight» является уникальным целым числом, это вызывает ошибку «column starid не уникальна» и не позволяет мне прогрессировать. Однако DISTINCT, похоже, проблема, выполняющая запрос без DISTINCT и без попытки вставить данные в таблицу hilight работает успешно и быстро. – Awebb

ответ

7

Хорошо, давайте начнем с рассмотрения вашего базового запроса. Я знаю, что у вас уже есть ответ, который работает, но я чувствую, что мне нужно объяснить вам, что происходит в вашем запросе.

INSERT INTO hilight 
SELECT DISTINCT 
    s.starid 
FROM planets AS p, stars AS s, moons AS m 
WHERE s.starid=(
    SELECT 
     starid 
    FROM planets 
    WHERE orbitdistance=(
      SELECT 
       MAX(orbitdistance) 
      FROM planets 
      ) 
     ); 

Так вот в вашей статье FROM вы также используете несколько старый стиль соединяет. У вас также отсутствует пункт ON. Это называется CROSS JOIN, который будет производить то, что мы называем декартовым произведением. В результирующем наборе будет количество строк в первой таблице, умноженное на количество строк во второй таблице и т. Д. И т. Д.

Таким образом, мы можем исправить это, просто установив синтаксис соединения и присоединившись к отношениям, которые вы указали на диаграмме.

INSERT INTO hilight 
SELECT --DISTINCT probably no longer needed as we aren't artifficially creating duplicate rows 
    s.starid 
FROM planets AS p 
inner join stars AS s 
    on s.StarID = p.starid 
inner join moons AS m 
    m.planetID = p.planetID 
WHERE s.starid=(
    SELECT 
     starid 
    FROM planets 
    WHERE orbitdistance=(
      SELECT 
       MAX(orbitdistance) 
      FROM planets 
      ) 
     ); 

После дальнейшего анализа вы присоединяетесь к столу лун, но не используют какой-либо из данных а также не ограничивая результирующий набор. Это означает, что вы не получаете никакой выгоды от этого в своем запросе и можете быть вырезаны прямо.

INSERT INTO hilight 
SELECT --DISTINCT probably no longer needed as we aren't artifficially creating duplicate rows 
    s.starid 
FROM planets AS p 
inner join stars AS s 
    on s.StarID = p.starid 
WHERE s.starid=(
    SELECT 
     starid 
    FROM planets 
    WHERE orbitdistance=(
      SELECT 
       MAX(orbitdistance) 
      FROM planets 
      ) 
     ); 

Теперь при дальнейшем анализе, если мы посмотрим на вашем предложении WHERE кажется, что это совершенно излишним. Мне кажется, что нет причин идти на планету дважды, чтобы получить предикат, когда вы можете просто сопоставить максимальное расстояние до орбиты до таблицы планет. Это также устраняет любые причины присоединиться к звездам таблицы.

INSERT INTO hilight 
SELECT 
    p.starid 
FROM planets AS p 
WHERE p.orbitdistance= 
    (
    SELECT 
     MAX(orbitdistance) 
    FROM planets 
    ) 

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

ОБНОВЛЕНИЕ: при дальнейших проверках этот GalaSQL выглядит довольно ужасно и имеет массовую устаревшую информацию, и я настоятельно рекомендую не использовать его.

+0

Это очень полезно и имеет большой смысл, спасибо. Через GalaXQL мне показалось, что значение должно проходить через каждую таблицу, прежде чем вставляться в hilight. Очевидно, это не так, и я немного смущен тем, что мне не придется иметь дело с этим конкретным препятствием в программировании. – Awebb

1

Вы можете удалить первый выбрать таким образом, что это будет liook как ...

INSERT INTO hilight 
SELECT DISTINCT p.starid 
FROM planets p 
WHERE orbitdistance=(
    SELECT MAX(orbitdistance) 
    FROM planets) 
; 

Вы также можете удалить отчетливый, если вы не имели конкретного причина его включения.

+0

Это работает намного эффективнее, спасибо. Похоже, я был намного старше, думая о прохождении между столами. – Awebb

0

Вы также можете использовать CROSS Apply.

INSERT INTO hilight 
SELECT P.startid 
FROM planets P 
CROSS APPLY (SELECT MAX(orbitdistance) as maxVal FROM planets) T 
WHERE P.orbitdistance = T.maxVal 
Смежные вопросы