Order by 子句在多次连接后行为不正确

Order by clause not behaving correctly after several joins

这是我的查询:

SELECT DISTINCT `post_data`. * , pv.`seller_id` , pv.`islimited` , pv.`isquantity` , pv.`isslider`, `price`.`original_price` , `price`.`discount_percentage` , `timelimit`.`start_date` , `timelimit`.`expire_date` , `quantity`.`in_stock`, `currency`.`currency_symbol`, `seller`.`directory`, `post_to_cat`.`cat_id`, count(`sales`.`sales_id`) as sale FROM `post_view` AS pv
INNER JOIN `post_data` ON pv.`post_id` = `post_data`.`post_id` AND pv.`status` = 1 
INNER JOIN `price` ON pv.`post_id` = `price`.`post_id` 
INNER JOIN `currency` ON `price`.`currency_id` = `currency`.`currency_id` 
INNER JOIN `seller` ON pv.`seller_id` = `seller`.`seller_id` 
INNER JOIN `post_to_cat` ON `post_to_cat`.`cat_id` = 1 AND `post_to_cat`.`post_id` = `post_data`.`post_id` 
LEFT JOIN `timelimit` ON ( CASE WHEN pv.`islimited` = 1 THEN `timelimit`.`post_id` ELSE -1 END ) = pv.`post_id`
LEFT JOIN `quantity` ON  ( CASE WHEN pv.`isquantity` = 1 THEN `quantity`.`post_id` ELSE -1 END ) = pv.`post_id`
LEFT JOIN `sales` ON `sales`.`post_id` = pv.`post_id` AND `sales`.`status` = 1 
WHERE pv.`status` = 1
ORDER BY pv.`post_id` DESC LIMIT 1 

ORDER BY DESC 不起作用,它只是 table 的第一行 returns,但我想获得最高的 post_id 值行。我犯了什么错误?

AS @Alex 在评论中说你最后有一个 LIMIT 1,为了便于阅读,你可能应该将最后一个 LEFT JOIN 括起来。

我认为这里的问题主要是由于执行聚合(使用 COUNT())函数而没有任何分组依据。虽然,您似乎不一定需要它,因为您只希望对有问题的 post 计数。

如果您尝试收集单个 post 的所有信息,我会调整您的 WHERE 子句,使其有条件仅收集 post 的信息] ID最大的

不要按 ID 排序并限制为 1,而是使用子查询来获取最大的 ID,如下所示:

...
WHERE pv.status = 1 AND post_data.slug = 'abc' AND pv.post_id = (SELECT MAX(post_id) FROM post_view);

正如@McAdam331 所说,我们需要数据样本和 sql fiddle 来调查您的查询有什么问题。但目前我有一些关于如何改进和调试您的查询的建议。

首先,我在你的查询中看到主要的和最左边的 table 是 post_view 所以所有其他 table 应该是 LEFT JOIN 如果你想要获得最大 ID。只有当您认为其他 table 可以 过滤 您的主要 table 并且顺序或结果可能是 时,您才应该使用 INNER JOIN其他 table 依赖。但在你的情况下,我认为没有理由使用 INNER JOIN.

第二点是你的ON条件很奇怪:

LEFT JOIN `timelimit` ON ( CASE WHEN pv.`islimited` = 1 THEN `timelimit`.`post_id` ELSE -1 END ) = pv.`post_id`
LEFT JOIN `quantity` ON  ( CASE WHEN pv.`isquantity` = 1 THEN `quantity`.`post_id` ELSE -1 END ) = pv.`post_id`

我已经把它们改成了另一个

CASE WHEN pv.`islimited`=1 THEN `timelimit`.`start_date` ELSE NULL END as start_date ,
CASE WHEN pv.`islimited`=1 THEN `timelimit`.`expire_date` ELSE NULL END as expire_date,
CASE WHEN pv.`isquantity`=1 THEN  `quantity`.`in_stock` ELSE NULL END as in_stock,

但我还是不喜欢。这对我来说似乎毫无用处。当我阅读 CASE WHEN pv.islimited=1 THEN timelimit.start_date ELSE NULL END as start_date 时没有任何意义,所以如果标记 pv.islimited=0 你不需要 start_date?你确定吗?

我可以建议的最后一件事:尝试使用我的查询,甚至是您的查询。但是在调试的时候一步步添加每个table。所以第一个查询只是:

SELECT 
pv.`post_id`, pv.`seller_id` , pv.`islimited` , pv.`isquantity` ,
pv.`isslider`
FROM `post_view` AS pv
WHERE pv.`status` = 1 
ORDER BY pv.`post_id` DESC 
LIMIT 1 

如果 returns 正确 post_id 添加下一个 table:

SELECT 
pv.`post_id`, pv.`seller_id` , pv.`islimited` , pv.`isquantity` ,
pv.`isslider`, 
`post_data`. * 
FROM `post_view` AS pv
LEFT JOIN `post_data` 
ON pv.`post_id` = `post_data`.`post_id` 
WHERE pv.`status` = 1 
  AND `post_data`.`slug` = 'abc' 
ORDER BY pv.`post_id` DESC 
LIMIT 1 

检查结果。并一步步继续。

是的,这需要时间。但那是调试过程。这可能是完成该查询的最快方式。 :-)

SELECT `post_data`. * ,
pv.`post_id`, pv.`seller_id` , pv.`islimited` , pv.`isquantity` ,
pv.`isslider`, `price`.`original_price` , `price`.`discount_percentage` , 
CASE WHEN pv.`islimited`=1 THEN `timelimit`.`start_date` ELSE NULL END as start_date ,
CASE WHEN pv.`islimited`=1 THEN `timelimit`.`expire_date` ELSE NULL END as expire_date,
CASE WHEN pv.`isquantity`=1 THEN  `quantity`.`in_stock` ELSE NULL END as in_stock,
 `currency`.`currency_symbol`, `seller`.`directory`, `post_to_cat`.`cat_id`, count(`sales`.`sales_id`) as sale 
FROM `post_view` AS pv
LEFT JOIN `post_data` 
ON pv.`post_id` = `post_data`.`post_id` 
LEFT JOIN `price` 
ON pv.`post_id` = `price`.`post_id` 
LEFT JOIN `currency` 
ON `price`.`currency_id` = `currency`.`currency_id` 
LEFT JOIN `seller` 
ON pv.`seller_id` = `seller`.`seller_id` 
LEFT JOIN `post_to_cat` 
ON `post_to_cat`.`cat_id` = 1 
  AND `post_to_cat`.`post_id` = pv.`post_id` 
LEFT JOIN `timelimit` 
ON `timelimit`.`post_id` = pv.`post_id`
LEFT JOIN `quantity` 
ON quantity`.`post_id` = pv.`post_id`
LEFT JOIN `sales` 
ON `sales`.`post_id` = pv.`post_id` 
  AND `sales`.`status` = 1 
WHERE pv.`status` = 1 
  AND `post_data`.`slug` = 'abc' 
GROUP BY pv.`post_id` 
ORDER BY pv.`post_id` DESC 
LIMIT 1 

编辑 1 - 根据@McAdam331 关于 count() 函数没有 GROUP BY

的通知添加了最后一个 GROUP BY pv.post_id