0

このクエリが期待どおりに機能しない理由がわかりません。私は馬のテーブルとファイルテーブルを持っています。ファイル テーブルには列 "fk_object" と "fk_id" があるため、fk_object="horse_photo" と fk_id=725 のようなレコードを取得できます。ファイル テーブルには is_default 列と position 列も含まれているため、プロファイル画像となるファイル (写真) を取得できます。ただし、デフォルトの写真や最初の位置ファイルさえも取得していません。このクエリが期待どおりに機能しない理由と、適切な解決策を教えてください。ありがとう!

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 は、0 から始まる UNSIGNED INT です。結合されたファイルは、最初に is_default=1 である必要があり、次に File.position=0 (または最小の int) に解決されます。 .

私が得ている結果: horse.id ASC で並べ替えられたリストですが、結合されたファイルは最初のファイルのように見えます (プライマリ ID 列で並べ替えられています)。

4

3 に答える 3

0

私の最初の回答に対するコメントであなたの質問に答えるには、いいえ、結合で使用されるものを注文することはできません。制限のあるコマンドを使用しないと、ビュー、インライン関数、派生テーブル、CTE、またはサブクエリを注文することはできません。

では、これをもう一度試してみましょう。馬ごとに 1 つのレコードを返すクエリが必要です。デフォルトの写真がある場合は、その写真を返します。デフォルトがない場合は、位置番号が最も小さいものを返します。以下に示すように、私は CTE の大ファンです。CTE を初めて使用する場合、これは混乱を招くかもしれませんが、一度マスターすると、生活がずっと楽になります!

最初の CTE (つまり、Default_Photo) は、馬ごとに、存在するデフォルトの写真のデータを返します。デフォルトの写真がない場合、その馬の記録はありません。

2 番目の CTE (つまり、Next_Best_Photos) は、デフォルトではない写真の最小位置番号を使用して、馬ごとに 1 つの行を返します。これには、デフォルトの写真がある馬の場合でも、デフォルト以外の写真が含まれます。それが本来あるべき姿です。

3 番目の CTE (つまり、Final_Dataset) は、馬ごとに 1 つの個別の行を返します。その馬に対応する行が Default_Photos CTE にない場合 (つまり、デフォルトの写真がない場合)、最小位置の写真に関連付けられた情報が表示されます。

3 番目のクエリが必要な理由は、t-sql (私が使用するもの) では、distinct コマンドを使用すると、派生列で並べ替えることができないためです。

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 ごとに 1 つの行しか取得できないことを確実にする必要があるダッシュボードのデータセットを構築する方法は次のとおりです。

于 2013-11-13T23:21:25.813 に答える
0

あなたの問題は、馬のIDでグループ化していますが、選択している他の列で集計関数を使用していないことです.1つの列でグループ化すると、選択した他のすべての列は合計、または最大、最小などである必要があります。動作するはずです:

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;
于 2013-11-08T21:55:14.373 に答える