Неправильное использование UNION и ORDER BY? - PullRequest
53 голосов
/ 18 июля 2011

как я могу использовать объединение и порядок по в mysql?

select * from _member_facebook 
inner join _member_pts 
ON _member_facebook._fb_owner=_member_pts._username 
where _member_facebook._promote_point = 9 
ORDER BY RAND() limit 2 
UNION ALL
select * from _member_facebook 
inner join _member_pts 
ON _member_facebook._fb_owner=_member_pts._username 
where _member_facebook._promote_point = 8 limit 3

дай мне ошибку

#1221 - Incorrect usage of UNION and ORDER BY

любой можетпомощь?

Ответы [ 6 ]

74 голосов
/ 18 июля 2011

Попробуйте с помощью:

(
  select 
    * 
  from 
     _member_facebook 
   inner join 
     _member_pts 
   ON 
     _member_facebook._fb_owner=_member_pts._username 
  where 
    _member_facebook._promote_point = 9 
  ORDER BY RAND() 
  limit 2
) 
UNION ALL
(
  select 
    * 
  from 
    _member_facebook 
   inner join 
    _member_pts 
   ON 
     _member_facebook._fb_owner=_member_pts._username 
  where 
    _member_facebook._promote_point = 8 
  limit 3
)

Хотя, я думаю, вы должны поместить предложение ORDER BY в конце второго запроса

29 голосов
/ 18 июля 2011

С круглыми скобками:

(
    SELECT *
    FROM _member_facebook
    INNER JOIN _member_pts
    ON _member_facebook._fb_owner         =_member_pts._username
    WHERE _MEMBER_FACEBOOK._PROMOTE_POINT = 9
    ORDER BY RAND()
    LIMIT 2
)
UNION ALL
(
    SELECT *
    FROM _MEMBER_FACEBOOK
    INNER JOIN _MEMBER_PTS
    ON _MEMBER_FACEBOOK._FB_OWNER         =_MEMBER_PTS._USERNAME
    WHERE _MEMBER_FACEBOOK._PROMOTE_POINT = 8
    LIMIT 3
)

Сказал, что MySQL не обязателен сохранять внутреннюю сортировку во внешнем предложении - хотя он , вероятно, сделает это, так как ему все равно нужно отсортировать строки для вычисления соответствующего LIMIT статьи.

22 голосов
/ 06 мая 2015

Пояснение:

Важно понимать, как это работает, чтобы избежать "ошибок" в подобных случаях использования. Обратите внимание, что синтаксис union несколько «особенный»:

подсостояние union all подсостояние union all подсостояние [order by -clause] [limit -clause]

, где " subtatement " может быть опционально окружен ( и ). Некоторые рабочие примеры:

  • select 1 union all (select 2);
    select 1 union all  select 2  union all (select 3);
    select 1 union all (select 2) union all  select 3;
    select 1 union all (select 2) union all (select 3);
    select 1 union all (select 2) union all (select 3) union all  select 4;
    select 1 union all (select 2) union all  select 3  union all (select 4);
    

Однако , если вы окружите первую " подстанцию ​​" фигурными скобками, вы должны окружить все остальные " подстановку " s с фигурными скобками:

  • (select 1) union all (select 2) union all (select 3);
    

(Обратите внимание, что вышеупомянутый пункт не упоминается в официальных документах .)

В противном случае это синтаксическая ошибка:

  • mysql> (select 1) union all select 2; -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error in your SQL syntax; check the...
    mysql> (select 1) union all (select 2) union all  select 3; -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error...
    mysql> (select 1) union all  select 2  union all (select 3); -- error because not all "substatement"s are braced
    ERROR 1064 (42000): You have an error...
    

Далее, каждое « подсостояние » может содержать where, group by, having, join, limit, но не order by.

Если вы хотите использовать order by, « подстановка », содержащая order by, должна быть заключена в фигурные скобки. (Это означает, что они больше не являются обязательными.)

Теперь, если мы снова посмотрим на синтаксис:

подсостояние union all подсостояние union all подсостояние [order by -clause] [limit -clause]

мы видим, что весь оператор union заканчивается необязательным order by / limit. Эти два ключевых слова применяются ко всему оператору union, а не только к последнему " substatement ":

  • mysql> select 1
        -> union all
        -> select 2 limit 1;
    +---+
    | 1 |
    +---+
    | 1 |
    +---+
    1 row in set (0.00 sec)
    
    mysql>
    

Мы уже упоминали ранее, что ключевое слово limit может также применяться к отдельным " подстатьям " s:

  • mysql> select 1 limit 1
        -> union all
        -> select 2;
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

Если вы хотите применить limit к последнему « подстановке » (в отличие от всего оператора union), вы должны окружить последний « подстанция"с фигурными скобками:

  • mysql> select 1
        -> union all
        -> (select 2 limit 1);
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

Чтобы применить limit к последнему " подсостоянию " , а также ко всему оператору union, используйте:

  • mysql> select 1
        -> union all
        -> (select 2 limit 1)limit 1;
    +---+
    | 1 |
    +---+
    | 1 |
    +---+
    1 row in set (0.00 sec)
    
    mysql>
    

То же самое с order by:

  • mysql> select 1
        -> union all
        -> (select 2 order by 1)order by 1;
    +---+
    | 1 |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mysql>
    

Но учтите, что применение order by к " подсостоянию " является бессмысленным , поскольку в документах явно указано , что order by гарантируется только ( ср. ) для работы применительно ко всему выражению union:

* * & Тысяча сто семьдесят три puncsp; * +1174 * & Ndash; & раздел; & Ndash; * +1175 * & EnSP; ..use из ORDER BY для отдельных операторов SELECT ничего не говорит о порядке, в котором строки появляются в конечном результате ..

Единственный способ order by будет иметь смысл в « подстановке », если вы объедините его с limit:

& puncsp; & Ndash; & раздел; & Ndash; & EnSP; ..использование ORDER BY в этом контексте обычно связано с LIMIT, так что оно используется для определения подмножества выбранных строк для извлечения для SELECT, даже если оно не обязательно влияет на порядок этих строк в конечном UNION результате.

Кроме того, если вы хотите объединить select <strong><em>into</em></strong> с union, будет больше "ловушек", на которые стоит обратить внимание. См. выпуск 32858 относительно этого.

0 голосов
/ 13 октября 2018

Я думаю, что использование скобок обязательно, если вы используете order by или limit или оба. Я пытался работать над запросом, используя лимит и порядок взаимозаменяемо без скобок, и запрос не работал. Это работало только после добавления скобок.

0 голосов
/ 04 сентября 2018

try () я думаю, что

(SELECT  CITY,LENGTH(CITY) FROM STATION WHERE LENGTH(CITY)=(SELECT MIN(LENGTH(CITY)) FROM STATION) ORDER BY CITY LIMIT 1) 
UNION ALL
(SELECT  CITY,LENGTH(CITY) FROM STATION WHERE LENGTH(CITY)=(SELECT MAX(LENGTH(CITY)) FROM STATION) ORDER BY CITY LIMIT 1);
0 голосов
/ 24 мая 2016

Правильно:

(SELECT *
   FROM _member_facebook
   INNER JOIN _member_pts ON _member_facebook._fb_owner=_member_pts._username
   WHERE _member_facebook._promote_point = 9 LIMIT 2)
UNION ALL
  (SELECT *
   FROM _member_facebook
   INNER JOIN _member_pts ON _member_facebook._fb_owner=_member_pts._username
   WHERE _member_facebook._promote_point = 8 LIMIT 3)
ORDER BY 1
...