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

您的问题是您按马 id 分组,但没有在您选择的其他列上使用任何聚合函数,如果您在一个列上分组,您选择的每个其他列必须是总和、最大值或最小值等。这个应该管用:

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 回答
0

如果我理解您的问题和当前结果,那么问题在于您没有指定 File.is_Default=1。再加上您按 Horse.id 分组的事实,每匹马都会给您一排它首先找到的照片。

如果您将“file.is_default=1”添加到您的连接条件或新的 Where 子句中,那么您应该得到您想要的结果。如果您将“file.is_default=1”放入连接条件并且没有默认照片,则任何文件列都将为该马返回空值。如果在 Where 子句中输入“file.is_default=1”,则结果集中不会出现没有默认照片的马。

此外,为了让人们更容易阅读您的代码,我建议您为表格设置别名,并可能缩进您的代码,而不是将每个子句的所有内容都放在一行中。

于 2013-11-08T22:55:22.800 回答
0

要在我的第一个答案的评论中回答您的问题,不,您不能订购连接中使用的任何东西。如果不使用限制性命令,您将无法对视图、内联函数、派生表、CTE 或子查询进行排序。

所以,让我再试一次。您需要一个为每匹马返回一条记录的查询。如果有默认照片,则返回该照片。如果没有默认值,则返回位置编号最小的那个。现在,我是 CTE 的忠实粉丝,如下所示。如果您是 CTE 的新手,这可能会让人感到困惑,但是一旦您掌握了它们,它们会让您的生活变得更轻松!

第一个 CTE(即 Default_Photo)将为每匹马带回任何存在的默认照片的数据。如果没有默认照片,则该马将没有记录。

第二个 CTE(即 Next_Best_Photos)将为每匹马带回一排,其中包含非默认照片的最小位置编号。这将包含非默认照片,即使对于有默认照片的马也是如此。这就是它应该的方式。

第三个 CTE(即 Final_Dataset)将为每匹马带回一个不同的行。如果那匹马在 Default_Photos CTE 中缺少相应的行(即它没有默认照片),那么它将显示与具有最小位置的照片相关联的信息。

您需要第三个查询的原因是,在 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 只能得到一行。

于 2013-11-13T23:21:25.813 回答