MYSQL语句问题 - INNER JOIN,LEFT JOIN WITH GROUP BY和MAX

时间:2018-01-28 04:43:35

标签: mysql

我不能因为我的生活而得到这样的陈述。

SELECT max(pm.timestamp), pm.id, pm.p_media_user_id, pm.p_media_type, 
pm.p_media_file, pm.wall_post, pm.p_media_location,pm.p_media_location_name, 
pm.p_media_category, pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id, 
pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image 

FROM p_media as pm 

INNER JOIN p_users as pu ON pm.p_media_user_id = pu.fb_id 

LEFT JOIN p_alerts as pa ON pm.id = pa.post_id AND pa.p_source_alert_id ='3849084' 

group by pm.p_media_user_id;

我唯一遇到的问题是max(pm.timestamp),在分组之后我希望它能在p_media表中显示最新的行,但相反它却正好相反并显示最古老的行。所以,我需要p_media表中的最新行,这些行按用户ID分组,这些行加入了p_users表。

如果有人帮忙,请提前致谢。

3 个答案:

答案 0 :(得分:2)

正如其他人已经指出的那样,您通过p_media_user_id列聚合,然后选择其他非聚合列。这要么根本不会运行,要么会运行但是给出非确定的结果。但是,对于每个p_media,您似乎只想要p_media_user_id表中的最新记录。 如果是这样,那么这似乎是您打算运行的查询:

SELECT
    pm1.timestamp, pm1.id, pm1.p_media_user_id, pm1.p_media_type, pm1.p_media_file,
    pm1.wall_post, pm1.p_media_location, pm1.p_media_location_name, 
    pm1.p_media_category, pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id,
    pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image 
FROM p_media as pm1
INNER JOIN
(
    SELECT p_media_user_id, MAX(timestamp) AS max_timestamp
    FROM p_media
    GROUP BY p_media_user_id
) pm2
    ON pm1.p_media_user_id = pm2.p_media_user_id AND
       pm1.timestamp = pm2.max_timestamp
INNER JOIN p_users AS pu
    ON pm1.p_media_user_id = pu.fb_id 
LEFT JOIN p_alerts AS pa
    ON pm1.id = pa.post_id AND
       pa.p_source_alert_id = '3849084';

答案 1 :(得分:1)

您的查询未执行您认为正在执行的操作。使用GROUP BY时,只有GROUP BY子句中显示的列才能在SELECT中使用,而无需使用聚合函数。 GROUP BY子句 MUST 中的所有列在将其添加到SELECT时都会在聚合函数中使用。

这是标准,对于遵循标准的所有数据库,您将从查询中收到错误。出于某种原因,MySQL决定不遵守此标准,并且不会返回任何错误。这非常糟糕,因为您的查询将会运行,但结果无法预测。因此,您会认为查询很好,并且会想知道为什么会得到错误的结果,而实际上您的查询无效。

MySQL终于解决了这个问题并starting with MySQL 5.7.5, the ONLY_FULL_GROUP_BY SQL mode is enabled by default。他们给出的理由相当愚蠢:因为GROUP BY处理变得更加复杂,包括检测功能依赖性。,但至少他们已经改变了默认值并从MySQL 5.7.5开始,它的行为与大多数其他数据库一样。对于早期版本,如果您有权更改设置,我建议您启用ONLY_FULL_GROUP_BY,以便为此类无效查询获得明确错误。

在某些情况下,如果所有值完全相同,您实际上并不关心非聚合列返回的值。要在启用ONLY_FULL_GROUP_BY时让查询通过,请在这些列上使用ANY_VALUE()函数。这是一个更好的方法,因为它清楚地表明了你的意图。

要了解如何修复查询,可以阅读How do we select non-aggregate columns in a query with a GROUP BY clause。您需要自行加入p_media表格,只需在分组中选择p_media_user_idMAX(timestamp)

SELECT pm.timestamp, pm.id, pm.p_media_user_id, pm.p_media_type, pm.p_media_file,
       pm.wall_post, pm.p_media_location, pm.p_media_location_name, pm.p_media_category,
       pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id,
       pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image 
FROM p_media as pm
INNER JOIN (SELECT p_media_user_id, MAX(timestamp) AS max_time
            FROM p_media
            GROUP BY p_media_user_id
           ) pmm ON pm.p_media_user_id = pmm.p_media_user_id
                AND pm.timestamp = pmm.max_time
INNER JOIN p_users AS pu ON pm.p_media_user_id = pu.fb_id 
LEFT JOIN p_alerts AS pa ON pm.id = pa.post_id
                        AND pa.p_source_alert_id = '3849084';

答案 2 :(得分:0)

您应该能够在分组后添加ORDER BY,并告诉SQL您想要按[ASC或DESC]排序的列。

SELECT max(pm.timestamp), pm.id, pm.p_media_user_id, pm.p_media_type, 
pm.p_media_file, pm.wall_post, pm.p_media_location,pm.p_media_location_name, 
pm.p_media_category, pa.p_source_alert_id, pa.post_id, pa.p_target_alert_id, 
pu.fb_id, pu.username, pu.city, pu.sex, pu.main_image 

FROM p_media as pm 

INNER JOIN p_users as pu ON pm.p_media_user_id = pu.fb_id 

LEFT JOIN p_alerts as pa ON pm.id = pa.post_id AND pa.p_source_alert_id ='3849084' 

group by pm.p_media_user_id
ORDER BY pm.p_media_user_id DESC;