2013-11-08 5 views
0

Я не понимаю, почему этот запрос работает не так, как ожидалось. У меня есть стол для стола и столик для стола. В таблице файлов есть столбцы «fk_object» и «fk_id», поэтому я могу получить записи, такие как fk_object = «horse_photo» и fk_id = 725. В таблице файлов также есть столбцы is_default и position, поэтому я могу захватить файл (фотографию), который должен быть его профилем. Тем не менее, я не получаю файл по умолчанию или даже файл первой позиции. Может кто-нибудь объяснить мне, почему этот запрос работает не так, как ожидалось, и каким будет надлежащее решение? Благодаря!MySQL заказывает результаты соединения

SELECT `horse`.`id`, 
     `horse`.`name`, 
     `file`.`id` AS `fid`, 
     `file`.`is_default`, 
     `file`.`position` 
FROM `horse` 
LEFT OUTER JOIN `file` ON (`file`.`fk_id`=`horse`.`id` 
          AND `file`.`fk_object`="horse_photo") 
GROUP BY `horse`.`id` 
ORDER BY `horse`.`id` ASC, 
     `file`.`is_default` DESC, 
     `file`.`position` ASC; 

Чтобы быть ясным, я хочу получить всех лошадей и их фотографию по умолчанию (если таковая имеется).

Подробнее: File.is_default булева либо 0, либо 1. File.position беззнаковая INT, начиная с 0. Файл вступил сначала должно быть is_default = 1, а затем решить, чтобы File.position = 0 (или наименьший int).

Результаты, которые я получаю: Список, отсортированный по horse.id ASC, однако связанный с ним файл является только первым файлом (упорядоченным по столбцу первичного идентификатора).

ответ

0

Чтобы ответить на ваш вопрос в комментарии к моему первому ответу, нет, вы не можете заказать что-либо, используемое в соединении. Вы не можете заказывать представление, встроенную функцию, производную таблицу, CTE или подзапрос без использования ограничительных команд.

Итак, позвольте мне дать еще одну попытку. Вам нужен запрос, который возвращает одну запись на лошадь. Если есть фотография по умолчанию, верните эту фотографию. Если по умолчанию нет, верните номер с наименьшим номером позиции. Теперь я большой поклонник CTE, как вы увидите ниже. Если вы новичок в CTE, это может сбивать с толку, но они могут сделать вашу жизнь намного легче, как только вы овладеете ими!

Первый CTE (т. Е. Default_Photo) вернет для каждой лошади данные по любой фотографии по умолчанию, которая существует. Если фотографий по умолчанию нет, то для этой лошади не будет записи.

Второй CTE (т. Е. Next_Best_Photos) вернет одну строку для каждой лошади с минимальным номером позиции для фотографий, которые не являются стандартными. Это будет содержать фотографии не по умолчанию, даже для лошадей, у которых есть фотографии по умолчанию. Так оно и должно быть.

Третий CTE (т.е., Final_Dataset) вернет одну отдельную строку для каждой лошади. Если этой лошади отсутствует соответствующая строка в CTE Default_Photos (т. Е. Она не имеет фотографии по умолчанию), тогда она отображает информацию, связанную с фотографией, с минимальным положением.

Причина, по которой вам нужен третий запрос, заключается в том, что в t-sql (который я использую) при использовании отдельной команды он не позволит сортировать по производным столбцам.

With Default_Photos as (
Select H.ID 
    , F.ID as 'FID' 
    , F.Position 

From Horse H 
    Inner Join File F 
     on H.ID = F.ID 

Where F.is_default = 1 
) 

, Next_Best_Photo as (
Select H.ID 
    , F.ID as 'FID' 
    , Min(F.Position) as Min_Position 

From Horse H 
    Inner Join File F 
     on H.ID = F.ID 

Where F.is_default = 0 

Group by H.ID 
    , F.ID 
) 

, Final_Dataset as (
Select Distinct H.ID 
    , H.name 
    , F.ID as 'FID' 
    , Case 
     When DP.ID is null 
      Then 1 
      Else 0 
     End as is_default 
    , Case 
     When DP.ID is null 
      Then F2.Position 
      Else DP.Position 
     End as position 

From Horse H 
    Inner Join File F 
     on H.ID = F.ID 
    Left Outer Join Default_Photos DP 
     on H.ID = DP.ID 
    Left Outer Join Next_Best_Photo NBP 
     on H.ID = NBP.ID 
    Left Outer Join File F2 
     on NBP.FID = F2.ID 
      and NBP.Min_Position = F2.Position 
) 

Select * 

From Final_Dataset 

Order by id asc 
    , is_default desc 
    , position asc 

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

0

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

SELECT `horse`.`id`, `horse`.`name`, `file`.`id` AS `fid`, `file`.`is_default`, `file`.`position` 
FROM `horse` 
LEFT OUTER JOIN `file` ON (`file`.`fk_id`=`horse`.`id` AND `file`.`fk_object`="horse_photo") 
GROUP BY `horse`.`id`, `horse`.`name`, `file`.`id` AS `fid`, `file`.`is_default`, `file`.`position` 
ORDER BY `horse`.`id` ASC, `file`.`is_default` DESC, `file`.`position` ASC; 
+0

Это дало мне синтаксическую ошибку из-за GROUP BY 'file'.'id' AS' fid' ... если я изменил ее на просто 'file'.'id' или' fid', она выполняется. Тем не менее, это дает мне строку для каждого файла. Это намеченный результат? – jymboche

+0

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

+0

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

0

Если я понять ваш вопрос и текущие результаты, то проблема заключается в том, что вы не указываете, что File.is_Default = 1. Это, в сочетании с тем фактом, что вы группируете Horse.id, дает вам один ряд на лошадь с учетом того, какая фотография сначала находит.

Если вы добавите «file.is_default = 1» в критерии соединения или новое предложение Where, вы должны получить нужные результаты. Если вы поместите значение «file.is_default = 1» в критерии соединения и нет фотографии по умолчанию, любые столбцы файлов возвратят нулевое значение для этой лошади. Если вы поместите файл «file.is_default = 1» в предложение Where, лошадь с фотографией по умолчанию не появится в результирующем наборе.

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

+0

Ну ... Я хочу, чтобы она вернула фотографию, если она есть ... Давайте забудем is_default на минуту и ​​скажем, что я хочу вернуть первый файл, отсортированный по алфавиту по имени файла. Нельзя ли просто заказать соединение произвольно? P.S Я отформатировал SQL выше. – jymboche

Смежные вопросы