简体   繁体   中英

Error in SQL query, unsure how to fix

I am getting an error in a query:

Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group by `messages`.`to_id` UNION SELECT `users`.`username` as 'subj' at line 13

I didn't write the query, and not sure what union does so not sure how to fix it.

select `thread`.`subject`,
       `thread`.`id`, 
       max(`thread`.`mostrecent`) as 'mostrecent',
       sum(`thread`.`from` + `thread`.`to`) as 'messages' 
from (
    SELECT `users`.`username` as 'subject', 
           `messages`.`to_id` as 'id' , 
           max(`messages`.`created`) as 'mostrecent',
           count(*) as 'from',
           0 as 'to' from `messages` 
           join `users` on `messages`.`to_id` = `users`.`id` 
           where `messages`.`from_id` = $id 
           group by `messages`.`to_id` 
    UNION 
    SELECT `users`.`username` as 'subject',
           `messages`.`from_id` as 'id', 
           max(`messages`.`created`) as 'mostrecent', 
           0 as 'from', 
           count(*) as 'to' from `messages` 
           join `users` on `messages`.`from_id` = `users`.`id` 
           where `messages`.`to_id` = $id
           group by `messages`.`from_id`
) as thread group by `thread`.`subject` order by max(`thread`.`mostrecent`) desc

you cannot order by an aggregate function and you dont have quotes around your $id which php requires... see my note at the end about sql injection

SELECT `thread`.`subject`,
       `thread`.`id`, 
       max(`thread`.`mostrecent`) as 'mostrecent',
       sum(`thread`.`from` + `thread`.`to`) as 'messages' 
from (
    SELECT `users`.`username` as 'subject', 
           `messages`.`to_id` as 'id' , 
           max(`messages`.`created`) as 'mostrecent',
           count(*) as 'from',
           0 as 'to' from `messages` 
           join `users` on `messages`.`to_id` = `users`.`id` 
           where `messages`.`from_id` = $id 
-- ------------------------------------^---^ = needs quotes
           group by `messages`.`to_id` 
    UNION 
    SELECT `users`.`username` as 'subject',
           `messages`.`from_id` as 'id', 
           max(`messages`.`created`) as 'mostrecent', 
           0 as 'from', 
           count(*) as 'to' from `messages` 
           join `users` on `messages`.`from_id` = `users`.`id` 
           where `messages`.`to_id` = $id
-- ----------------------------------^---^ = needs quotes
           group by `messages`.`from_id`
) as thread group by `thread`.`subject` order by max(`thread`.`mostrecent`) desc
-- -----------------------------------------------^------------------------^ = bad

instead

try changing it to just mostrecent because you already pulled out the max and gave it the alias mostrecent.. you can reference an alias in anything after the WHERE so GROUP BY and beyond including the ORDER BY

ORDER BY mostrecent DESC

so the final query should look like this...

SELECT 
    `thread`.`subject`,
    `thread`.`id`, 
    MAX(`thread`.`mostrecent`) AS 'mostrecent',
    SUM(`thread`.`from` + `thread`.`to`) AS 'messages' 
FROM 
(   SELECT 
        `users`.`username` AS 'subject', 
        `messages`.`to_id` AS 'id' , 
        MAX(`messages`.`created`) AS 'mostrecent',
        COUNT(*) AS 'from',
        0 AS 'to' 
    FROM `messages` 
    JOIN `users` ON `messages`.`to_id` = `users`.`id` 
    WHERE `messages`.`from_id` = '$id' 
    GROUP BY `messages`.`to_id` 

    UNION 

    SELECT 
        `users`.`username` AS 'subject',
        `messages`.`from_id` AS 'id', 
        MAX(`messages`.`created`) AS 'mostrecent', 
        0 AS 'from', 
        COUNT(*) AS 'to' 
    FROM `messages` 
    JOIN `users` ON `messages`.`from_id` = `users`.`id` 
    WHERE `messages`.`to_id` = '$id'
    GROUP BY `messages`.`from_id`
) AS thread 
GROUP BY `thread`.`subject` 
ORDER BY mostrecent DESC

NOTE

this query is vunerable to sql injection and I would recommend you parameterize your query and bind the $id to the query afterwards

you should read my post about writing a safer query...

Both your inner queries, and your outer query should be reworked to include both columns on the GROUP BY instead of just one:

select 
    `thread`.`subject`,
    `thread`.`id`, 
    max(`thread`.`mostrecent`) as 'mostrecent',
    sum(`thread`.`from` + `thread`.`to`) as 'messages' 
from 
(
    SELECT 
        `users`.`username` as 'subject', 
        `messages`.`to_id` as 'id' , 
        max(`messages`.`created`) as 'mostrecent',
        count(*) as 'from',
        0 as 'to' 
    FROM `messages` 
    JOIN `users` on `messages`.`to_id` = `users`.`id` 
    WHERE `messages`.`from_id` = $id 
    GROUP BY `users`.`username`, `messages`.`to_id` 
UNION 

    SELECT 
        `users`.`username` as 'subject',
        `messages`.`from_id` as 'id', 
        max(`messages`.`created`) as 'mostrecent', 
        0 as 'from', 
        count(*) as 'to' 
    FROM `messages` 
    JOIN `users` on `messages`.`from_id` = `users`.`id` 
    WHERE `messages`.`to_id` = $id
    GROUP BY `users`.`username`, `messages`.`from_id`
) as thread 
GROUP BY `thread`.`subject`, `thread`.`id`
ORDER BY max(`thread`.`mostrecent`) desc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM