我不明白为什么这个查询没有按预期工作。我有一张马桌和文件桌。文件表有“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列排序)。
答案 0 :(得分: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;
答案 1 :(得分:0)
如果我理解您的问题和您当前的结果,那么问题是您没有指定File.is_Default = 1。这与你通过Horse.id进行分组这一事实相结合,每匹马都会给你一行,而不管它首先找到哪一张照片。
如果您将“file.is_default = 1”添加到您的加入条件或新的Where子句,那么您应该获得所需的结果。如果将“file.is_default = 1”放在连接条件中并且没有默认照片,则任何文件列都将返回该匹配的空值。如果在Where子句中放入“file.is_default = 1”,则没有默认照片的马将不会出现在结果集中。
此外,为了让人们更容易阅读您的代码,我建议您对表格进行别名处理,并可能缩进代码,而不是将每个子句的所有内容放在一行上。
答案 2 :(得分: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只能获得一行。