Mysql union all error

В не очень далеком прошлом мне пришлось покопаться немного в исходном коде MySQL, и разобраться в некоторых аспектах его работы. В ходе работы лопаткой, и экспер...

Время прочтения
8 мин

Просмотры 62K

В не очень далеком прошлом мне пришлось покопаться немного в исходном коде MySQL, и разобраться в некоторых аспектах его работы. В ходе работы лопаткой, и эксперимeнтов, я наткнулся на несколько очень интересных особенностей, часть из которых просто забавна, а в случае некоторых бывает очень интересно понять, чем руководствовался программист, который принимал решение сделать именно так.

Начнем с такого интересного типа, как ENUM.

mysql> CREATE TABLE enums(a ENUM('c', 'a', 'b'), b INT, KEY(a));
Query OK, 0 rows affected (0.36 sec)

mysql> INSERT INTO enums VALUES('a', 1), ('b', 1), ('c', 1);
Query OK, 3 rows affected (0.05 sec)
Records: 3  Duplicates: 0  Warnings: 0

Итак, у нас есть таблица, в ней есть два столбца. У первого, a, тип ENUM, у второго, b, INT. В таблице три строки, у всех трех значение b равно 1. Интересно, чему равны минимальный и максимальный элементы в столбце a?

mysql> SELECT MIN(a), MAX(a) FROM enums;
+--------+--------+
| MIN(a) | MAX(a) |
+--------+--------+
| c      | b      |
+--------+--------+
1 row in set (0.00 sec)

Кажется странным, было бы разумно, если бы самым маленьким был ‘a’, а самым большим — ‘c’.
А что если выбрать минимум и максимум только среди тех строк, где b = 1? То есть, среди всех строк?

mysql> SELECT MIN(a), MAX(a) FROM enums WHERE b = 1;
+--------+--------+
| MIN(a) | MAX(a) |
+--------+--------+
| a      | c      |
+--------+--------+
1 row in set (0.00 sec)

Вот так мы заставили MySQL поменять свое мнение о том, как сравнивать поля в ENUM, просто добавив предикат.
Разгадка такого поведения заключается в том, что в первом случае MySQL использует индекс, а во втором нет. Это, конечно, не объясняет, почему MySQL сравнивает ENUMы по разному для сортировки в индексе, и при обычном сравнении.

Второй пример проще и лаконичнее:

mysql> (SELECT * FROM moo LIMIT 1) LIMIT 2;
+------+
| a    |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

Когда я показал этот запрос своему коллеге, который занимается разработкой парсера SQL, его вопрос был не «почему этот запрос возвращает две строки», а «как надо написать SQL парсер так, чтобы такой запрос был валидным, без того, чтобы написать правило, специально разрешающее такой запрос».

Интересно, что далеко не любой SELECT в скобках сработает, в частности, UNION в скобках — это синтаксическая ошибка:

mysql> (SELECT * FROM moo UNION ALL SELECT * FROM hru) LIMIT 2;
ERROR 1064 (42000): 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 'UNION ALL SELECT * FROM hru) LIMIT 2' at line 1

Еще несколько интересных примеров под катом

Вообще, с UNION и LIMIT далеко за примером странного поведения ходить не надо:

mysql> 
    -> SELECT 1 FROM moo LIMIT 1
    ->     UNION ALL
    -> SELECT 1 FROM hru LIMIT 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

Внезапно, вернулась только одна строка, хотя обе таблицы не пусты. Потому что второй LIMIT принадлежит всему запросу, а не только правой части UNION.

Тут надо рассказать о такой вещи, как shift-reduce conflict. В современных базах данных с открытым кодом парсер очень часто написан на bison. Такой парсер является так называемым L1-парсером, что значит, что парсер должен понять предназначение очередного токена, посмотрев не далее чем на один токен вперед. Например, в запросе выше смотря на слово LIMIT парсер не может понять, принадлежит этот LIMIT к второму запросу, или ко всему UNION. Когда правила написаны так, что возможны ситуации, при которых понять назначение токена посмотрев только на следующий токен нельзя, это называется shift-reduce conflict. В этом случае парсер будет выбирать решение базируясь на определенном наборе правил. Это очень плохо, потому что это приводит к тому, что вполне нормальные запросы приводят к ошибкам. Что, если я хочу в предыдущем запросе сделать LIMIT и второму SELECT, и UNION?

mysql>   SELECT 1 FROM moo
    ->       UNION ALL
    ->   SELECT 1 FROM hru LIMIT 1
    -> LIMIT 2;
ERROR 1064 (42000): 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 'LIMIT 2' at line 4

Так сделать нельзя, из-за shift-reduce конфликта. Смотря на первый LIMIT парсер еще не знает, что впереди будет второй, и ошибочно полагает, что первый лимит относится ко всему запросу.
В PostgreSQL в парсере shift-reduce conflicts нет совсем. Конкретно эта ситуация там разрешена за счет того, что LIMIT может быть только у UNION, но не у SELECT’ов которые он объединяет.
В MySQL таких конфликтов больше чем 160. Это поражает воображение, потому что это значит, что есть 160 мест, где парсер может не правильно понять, что от него хотят.

Хороший пример такого конфликта — это соединения. Как известно, в MySQL поддерживаются CROSS JOINs, у которых нет предиката, и INNER JOINs, у которых предикат есть. Вообще говоря, CROSS JOIN и INNER JOIN — это разные вещи, но в MySQL это синонимы. То есть у INNER JOIN может не быть предиката, а у CROSS JOIN он может быть. В частности, это приводит к интересной ошибке:

mysql> SELECT * FROM     
    ->     moo
    ->     INNER JOIN
    ->        hru
    ->        INNER JOIN
    ->        baa
    ->        ON hru.a = baa.a
    ->     ON moo.a = hru.a
    -> ;
ERROR 1064 (42000): 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 'ON moo.a = hru.a' at line 8

В момент, когда парсер видит первое ON, он еще не знает, что впереди его ждет второе, и сталкивается с выбором: либо это ON для hru и baa, либо hru и baa соединяются без предиката, а текущий ON — это ON для moo и результата соединения hru и baa. Парсер ошибочно выбирает второе, что приводит к совершенно не нужной в этой ситуации ошибке. Если INNER JOIN заменить на LEFT JOIN, для которого варианта без предиката не сущестует, то запрос выполнится:

mysql> SELECT * FROM     
    ->     moo
    ->     LEFT JOIN
    ->        hru
    ->        LEFT JOIN
    ->        baa
    ->        ON hru.a = baa.a
    ->     ON moo.a = hru.a
    -> ;
+------+------+------+------+
| a    | a    | b    | a    |
+------+------+------+------+
|    1 |    1 | 1    |    1 |
|    2 |    2 | 2    |    2 |
+------+------+------+------+
2 rows in set (0.00 sec)

Тут самое интересное, это то, что в Bison надо руками указать прямо в коде количество shift-reduce conflicts, иначе код не скомпилируется. То есть в какой-то момент времени один из программистов в MySQL сделал CROSS JOIN и INNER JOIN синонимами, что уже само по себе не имеет смысла, после чего попытался собрать код, и он не собрался с ошибкой компиляции, предупреждающей, что парсер теперь не сможет распарсить определенные запросы. На что тот программист, вместо того, чтобы сделать все правильно, нашел константу, указывающую на количество ошибок в парсере, и увеличил ее.

Хотя если говорить о том, какие интересные решения иногда программисты в MySQL принимают, то лучше всего вспомнить вот эту историю:
http://bugs.mysql.com/bug.php?id=27877
В ней один из программистов сознательно сделал в collation по умолчанию для utf8 букву ‘s’ равной символу ‘ß’. Это очень иронично, потому что единственный язык, в котором это хотя бы отдаленно могло бы иметь смысл — это немецкий, но именно это изменение делает этот collation совершенно не применимым к немецкому языку, потому что теперь строки, которые совершенно не равны друг другу, становятся равны.
Это изменение было не только бесполезным, оно еще и сделало процесс перехода с 5.0 на 5.1 для баз данных с utf8 строками на немецком очень болезненным, потому что уникальные индексы внезапно начали содержать повторяющиеся элементы.

Говоря о collations, я еще очень люблю вот такой пример:

Пусть у нас есть таблица с тремя строками с разными collations:

CREATE TABLE strings(
    swedish VARCHAR(100) COLLATE utf8_swedish_ci,
    spanish VARCHAR(100) COLLATE utf8_spanish_ci,
    bin VARCHAR(100) COLLATE utf8_bin
);

Выполним такой запрос:

mysql> SELECT * FROM strings WHERE swedish > bin AND swedish < spanish;
ERROR 1267 (HY000): Illegal mix of collations (utf8_swedish_ci,IMPLICIT) and (utf8_spanish_ci,IMPLICIT) for operation '<'

MySQL разумно жалуется, что сравнивать swedish и spanish нельзя, потому что непонятно, как их сравнивать.
Давайте напишем совершенно идентичный запрос:

mysql> SELECT * FROM strings WHERE swedish BETWEEN bin AND spanish;
Empty set (0.00 sec)

Внезапно, запрос стал валидным, хотя он по прежднему должен сравнивать swedish и spanish строку. А если я хочу наоборот?

mysql> SELECT * FROM strings WHERE swedish BETWEEN spanish AND bin;
ERROR 1270 (HY000): Illegal mix of collations (utf8_swedish_ci,IMPLICIT), (utf8_spanish_ci,IMPLICIT), (utf8_bin,IMPLICIT) for operation 'between'

А наоборот нельзя.
Если покопаться в коде, то можно понять, что в MySQL BETWEEN реализован совершенно странным образом: если первый или второй парамерт имеют бинарный collation, то все строки будут сравниваться как бинарные, и collation будет проигнорирован. Но если бинарный collation у третьего аргумента, то такая же логика не применяется.

Говоря о том, как странно работают функции в MySQL, завершим эту статью самым красивым примером.

mysql> SELECT LEAST(9, 11);
+--------------+
| LEAST(9, 11) |
+--------------+
|            9 |
+--------------+
1 row in set (0.00 sec)

Тут никаких сюрпризов

mysql> SELECT LEAST("9", "11");
+------------------+
| LEAST("9", "11") |
+------------------+
| 11               |
+------------------+
1 row in set (0.00 sec)

Это тоже разумно, строка 11 меньше чем 9. А что будет, если 11 прибавить к 11?

mysql> SELECT LEAST("9", "11") + LEAST("9", "11");
+-------------------------------------+
| LEAST("9", "11") + LEAST("9", "11") |
+-------------------------------------+
|                                  18 |
+-------------------------------------+
1 row in set (0.00 sec)

Конечно, 18. Получается, функция возвращает разное значение в зависимости от контекста! А можно ли заставить один и тот же LEAST вернуть три разных значения в зависимости от контекста? Оказывается, да

mysql> SELECT LEAST("9e1", "110");
+---------------------+
| LEAST("9e1", "110") |
+---------------------+
| 110                 |
+---------------------+
1 row in set (0.00 sec)

mysql> SELECT LEAST("9e1", "110") + 0;
+-------------------------+
| LEAST("9e1", "110") + 0 |
+-------------------------+
|                      90 |
+-------------------------+
1 row in set (0.00 sec)

mysql> SELECT LEAST("9e1", "110") & -1;
+--------------------------+
| LEAST("9e1", "110") & -1 |
+--------------------------+
|                        9 |
+--------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+---------+------+------------------------------------------+
| Level   | Code | Message                                  |
+---------+------+------------------------------------------+
| Warning | 1292 | Truncated incorrect INTEGER value: '9e1' |
+---------+------+------------------------------------------+
1 row in set (0.00 sec)

Хотя тут надо сказать, что в одном случае мы встретили предупреждение. Но у нас все же получилось заставить один и тот же оператор с одними и теми же аргументами вернуть три разных значения.

Чтобы сделать еще более удивительное открытие, надо познакомиться с функцией NULLIF. Эта функция принимает два аргумента, и возвращает NULL, если они равны, или значение первого аргумента, если они не равны. Отложив в сторону вопрос о том, зачем такая функция вообще существует, давайте посмотрим на результат следующих двух запросов:

mysql> SELECT NULLIF(LEAST("9", "11"), "11") + 0;
+------------------------------------+
| NULLIF(LEAST("9", "11"), "11") + 0 |
+------------------------------------+
|                               NULL |
+------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT NULLIF(LEAST("9", "11"), "12") + 0;
+------------------------------------+
| NULLIF(LEAST("9", "11"), "12") + 0 |
+------------------------------------+
|                                  9 |
+------------------------------------+
1 row in set (0.00 sec)

В первом случае мы получили NULL, что говорит о том, что LEAST действительно равен строке «11». Во втором случае в таком же запросе, с такими же типами аргументов, но с другой константой в NULLIF мы получили значение 9! То есть при совершенно одинаковых типах параметров в первом случае LEAST вернул «11», а во втором — 9.
Но можно сделать еще лучше:

mysql> SELECT NULLIF(LEAST("9", "11"), "9") + 0;
+-----------------------------------+
| NULLIF(LEAST("9", "11"), "9") + 0 |
+-----------------------------------+
|                                 9 |
+-----------------------------------+
1 row in set (0.00 sec)

В этом запросе LEAST вернул что-то отличное от строки «9» (иначе бы NULLIF вернул NULL), однако он в тоже самое время вернул строку «9»!
Если посмотреть в код, то это действительно то, что происходит. LEAST выполняется дважды, первый раз сравнивая параметры, как строки, а второй раз — как целые числа.

The SQL UNION operator
The UNION operator is used to combine the result sets of two or more SELECT statements.
Note that the SELECT statement within the UNION must have the same number of columns. Columns must also have similar data types. Also, the order of the columns in each SELECT statement must be the same.
The UNION SQL grammar

SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2

Note: By default, the UNION operator picks a different value. If duplicate values are allowed, use UNION ALL.
SQL UNION ALL syntax

SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2

Also, the column name in the UNION result set is always equal to the column name in the first SELECT statement in the UNION.
Error reporting and resolution
When using the UNION operator, the following error can easily be reported:
Parse error: org. Apache. Hadoop. Hive. Ql. Parse. ParseException: line 5-0 always recognize input near “and” (” and “the UNION, ‘ ‘SELECT’ set in the operator
Simplify the code used as follows:

SELECT
    device_id
FROM
    tableA
UNION
(SELECT
    device_id
FROM
    tableB as a1
INNER JOIN tableC as a2
on a1.device_id = a2.device_id
)

This is mainly because the UNION operator can only join fields to fields, but not fields to tables or tables, even if the number of fields and their names and formats are the same.
Therefore, you can’t have parentheses around the UNION operator, because it’s easy for SQL to determine that this is a subquery/table and therefore to report an error when joining
The solution

    > SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D> SELECT FROM TABLE D
    Matters needing attention

      > Multiple UNION operators can be used in SQL statements. SELECT statements that use the UNION operator cannot contain their own ORDER BY or COMPUTE clauses. You can only use an ORDER BY or COMPUTE clause on the final combined result set (that is, after the last SELECT statement). The GROUP BY and HAVING clauses can be used in SELECT statements that use the UNION operator. By default, SQL Server 2005 evaluates statements containing the UNION operator from left to right. You can specify the order of evaluation using parentheses (I haven’t tested this thoroughly on any other platform, so avoid parentheses altogether, so if you need to specify the order of evaluation, you can simply write that part of the evaluation at the beginning of your SQL statement).

Read More:

If you’re getting “ERROR 1222 (21000): The used SELECT statements have a different number of columns” when using the UNION clause in a MySQL query, it’s probably because the number of columns returned by each SELECT statement is different.

For example, the first SELECT statement might return two columns, but the second SELECT statement returns three.

To fix this issue, make sure both SELECT statements return the same number of columns.

Example of Error

Here’s an example of code that produces the error:

SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;

Result:

ERROR 1222 (21000): The used SELECT statements have a different number of columns

Here, the first SELECT statement returns one column (TeacherName), but the second SELECT statement returns two columns (StudentId and StudentName).

Solution

The way to fix this issue is to ensure both SELECT statements return the same number of columns

So using the above example, we can either remove the extra column from our second SELECT statement:

SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;

Result:

+-------------+
| TeacherName |
+-------------+
| Warren      |
| Ben         |
| Cathy       |
| Bill        |
| Faye        |
| Jet         |
| Spike       |
| Ein         |
+-------------+

Or we can add another column to the first SELECT statement:

SELECT TeacherId, TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;

Result:

+-----------+-------------+
| TeacherId | TeacherName |
+-----------+-------------+
|         1 | Warren      |
|         2 | Ben         |
|         3 | Cathy       |
|         4 | Cathy       |
|         5 | Bill        |
|         6 | Bill        |
|         1 | Faye        |
|         2 | Jet         |
|         3 | Spike       |
|         4 | Ein         |
|         5 | Warren      |
+-----------+-------------+

Be mindful that you can get different results depending on which option you choose. This is because UNION returns distinct rows by default. When we add another column, there’s a possibility that a previously duplicate row now becomes a unique row, depending on the value in the extra column.

We can also use UNION ALL, which returns duplicate values:

SELECT TeacherId, TeacherName FROM Teachers
UNION ALL
SELECT StudentId, StudentName FROM Students;

Result:

+-----------+-------------+
| TeacherId | TeacherName |
+-----------+-------------+
|         1 | Warren      |
|         2 | Ben         |
|         3 | Cathy       |
|         4 | Cathy       |
|         5 | Bill        |
|         6 | Bill        |
|         1 | Faye        |
|         2 | Jet         |
|         3 | Spike       |
|         4 | Ein         |
|         5 | Warren      |
|         6 | Bill        |
+-----------+-------------+

Мне кажется, вы неправильно пользуетесь конструкцией ORDER BY в сочетании с UNION. Мануал на этот счет говорит следующее:

=========================================

To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one. The following example uses both clauses:

(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;

This kind of ORDER BY cannot use column references that include a table name (that is, names in tbl_name.col_name format). Instead, provide a column alias in the first SELECT statement and refer to the alias in the ORDER BY. (Alternatively, refer to the column in the ORDER BY using its column position. However, use of column positions is deprecated.)

Also, if a column to be sorted is aliased, the ORDER BY clause must refer to the alias, not the column name. The first of the following statements will work, but the second will fail with an Unknown column ‘a’ in ‘order clause’ error:

(SELECT a AS b FROM t) UNION (SELECT …) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT …) ORDER BY a;

To apply ORDER BY or LIMIT to an individual SELECT, place the clause inside the parentheses that enclose the SELECT:

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

Use of ORDER BY for individual SELECT statements implies nothing about the order in which the rows appear in the final result because UNION by default produces an unordered set of rows. If ORDER BY appears with LIMIT, it is used to determine the subset of the selected rows to retrieve for the SELECT, but does not necessarily affect the order of those rows in the final UNION result. If ORDER BY appears without LIMIT in a SELECT, it is optimized away because it will have no effect anyway.

To cause rows in a UNION result to consist of the sets of rows retrieved by each SELECT one after the other, select an additional column in each SELECT to use as a sort column and add an ORDER BY following the last SELECT:

(SELECT 1 AS sort_col, col1a, col1b, … FROM t1)
UNION
(SELECT 2, col2a, col2b, … FROM t2) ORDER BY sort_col;

To additionally maintain sort order within individual SELECT results, add a secondary column to the ORDER BY clause:

(SELECT 1 AS sort_col, col1a, col1b, … FROM t1)
UNION
(SELECT 2, col2a, col2b, … FROM t2) ORDER BY sort_col, col1a;

=========================================

Если вам не трудно, скиньте мне CREATE TABLE запрос для ваших таблиц. Попробую поиграть.

Ваш второй запрос оказался вложенным и как следствие будет долго выполняться, мне кажется.

Создайте следующие два набора результатов:

1). Запросите алфавитно упорядоченный список всех имен в OCCUPATIONS, за которым сразу следует первая буква каждой профессии в виде скобки (т.е. Заключенная в круглые скобки). Например: AnActorName (A), ADoctorName (D), AProfessorName (P) и ASingerName (S).

2). Запросите количество случаев каждого занятия в OCCUPATIONS. Сортируйте вхождения в порядке возрастания и выведите их в следующем формате:

There are total [occupation_count] [occupation]s.

Название таблицы: Занятия

Всего столбцов: Два = «Имя» и «Занятие», демонстрационная таблица показана ниже:

Изображение 28580

Результат выборки:

Ashely(P)
Christeen(P)
Jane(A)
Jenny(D)
Julia(A)
Ketty(P)
Maria(A)
Meera(S)
Priya(S)
Samantha(D)
There are total 2 doctors.
There are total 2 singers.
There are total 3 actors.
There are total 3 professors.

Мой подход:

(SELECT NAME, '(', SUBSTRING(OCCUPATION, 1, 1), ')' 
    FROM OCCUPATIONS ORDER BY NAME) 
UNION ALL 
(SELECT COUNT(*) FROM OCCUPATIONS GROUP BY OCCUPATION ORDER BY ASEC);

Ошибка:

ERROR 1222 (21000) at line 1: 
    The used SELECT statements have a different number of columns

Спасибо!

03 апр. 2016, в 23:17

Поделиться

Источник

16 ответов

Вы забыли использовать функцию CONCAT для склеивания выбранных данных

Попробуйте что-нибудь подобное (также см. Этот пример на sqlfiddle):

(
  SELECT CONCAT(NAME, '(', SUBSTRING(OCCUPATION, 1, 1), ')') as THETEXT, '1' as SELECTNUMBER
    FROM OCCUPATIONS
)
UNION ALL 
(
  SELECT CONCAT('There are total ', COUNT(*),' ', OCCUPATION, (IF (COUNT(*) > 1, 's',''))) as THETEXT, '2' as SELECTNUMBER
   FROM OCCUPATIONS GROUP BY OCCUPATION
)
ORDER BY SELECTNUMBER ASC, THETEXT ASC;

alexander.polomodov
03 апр. 2016, в 21:21

Поделиться

SELECT concat(NAME,concat("(",LEFT(occupation,1),")")) 
FROM OCCUPATIONS 
ORDER BY NAME ASC;

select CONCAT("There are a total of", " ",COUNT(occupation), " ",LCASE(occupation),"s",".")AS stat
from OCCUPATIONS
group by occupation
order by COUNT(occupation) ASC,occupation

Ganesh shinde
13 сен. 2017, в 07:28

Поделиться

Работал на хакерранке

SELECT Name || '(' || SUBSTR(Occupation,1,1) || ')'-- AS THETEXT, '1' AS SELECTNUMBER
    FROM OCCUPATIONS
    order by Name;

    SELECT 'There are a total of' || ' ' || COUNT(*) || ' ' || lower(Occupation) || 's.'
    FROM OCCUPATIONS  GROUP BY OCCUPATION                            
    ORDER BY COUNT(Occupation), lower(Occupation);

Ануар Алибеков
28 янв. 2019, в 14:05

Поделиться

SELECT CONCAT(name, '(', SUBSTRING(occupation, 1, 1), ')') as occ from occupations ORDER BY name;

SELECT concat('There are a total of ', COUNT(*), ' ', LCASE(occupation),  's.') from occupations GROUP BY occupation ORDER BY COUNT(*), occupation;

Это делает очарование.

abhiagNitk
20 янв. 2019, в 15:00

Поделиться

(Select name||'('||substr(Occupation,0,1)||')'  
from OCCUPATIONS)
Union All
(Select 'There are a total of '||count(*)||' '||lower(Occupation)||'s.'  
from OCCUPATIONS group by Occupation) 
order by 1;

Shruti Srivastava
23 сен. 2018, в 12:47

Поделиться

Я просто пробовал на хакерранке, и он работает, вам не нужно использовать Союз.

select concat(name,'(',upper(substring(occupation,1,1)),')') from occupations
order by name;

select concat("There are a total of",' ',count(occupation),' ',lower(occupation),'s',".")  from occupations
group by occupation
order by count(occupation) asc;

user2654920
01 июнь 2018, в 04:34

Поделиться

select concat(name,'(',left(occupation,1),')') from occupations order by name;


select concat('There are total of',' ',count(occupation),' ',lower(occupation),"s.") from occupations group by occupation order by count(occupation),occupation;

samarth tyagi
18 фев. 2018, в 12:50

Поделиться

Это работало для меня в MySQL

select concat(name,"(",substr(occupation,1,1),")") from occupations
order by name asc;

select concat('There are total ',count(*),' ',lower(occupation),'s.') as n from occupations
group by occupation
order by n asc;

rohan.k
11 май 2017, в 06:39

Поделиться

(
  SELECT CONCAT(NAME, '(', SUBSTRING(OCCUPATION, 1, 1), ')') as THETEXT
    FROM OCCUPATIONS
)
UNION ALL 
(
  SELECT CONCAT('There are total ', COUNT(*),' ', LOWER(OCCUPATION) ,(IF (COUNT(*) > 1, 's','')), '.') as THETEXT
   FROM OCCUPATIONS  group by  OCCUPATION
)
ORDER by THETEXT ASC;

Rahul Kumar
29 март 2017, в 21:01

Поделиться

//Just be careful for the format!

(select concat(name, '(',left(occupation,1),')') as text
from occupations
)
union all
(
   select concat(
       'There are total ', 
       count(*), ' ', lower(occupation), 
       case
        when COUNT(*) > 1 
        then 's'
       end
       ,
       '.'
    ) as text
    from occupations
    group by occupation
)
order by text asc;

Shawn
02 авг. 2016, в 22:06

Поделиться

SELECT * FROM (
    select distinct Name + '('+left(Occupation,1)+')'as a
    from OCCUPATIONS 
    union
    select  ('There are total ' +cast( count( Occupation) as nvarchar) + ' '+ lower(Occupation) +'s.') as b 
    from OCCUPATIONS
    GROUP BY OCCUPATION
    ) AS N
ORDER BY a

Это работает для меня на MS SQL Server.

Ashwini M
03 июль 2016, в 22:09

Поделиться

union требует, чтобы два запроса имели одинаковое количество столбцов, вы можете добавить любые некоторые столбцы ко второму запросу, чтобы сделать их похожими на первый, например SELECT COUNT (*), «col-1», «col-2», «col -3 ‘от

Nizar Ahmed
03 апр. 2016, в 22:28

Поделиться

SELECT * FROM (
    select distinct Name + '('+left(Occupation,1)+')'as a
    from OCCUPATIONS 
    union
    select  ('There are total ' +cast( count( Occupation) as nvarchar) + ' '+ lower(Occupation) +'s.') as b 
    from OCCUPATIONS
    GROUP BY OCCUPATION
    ) AS N
ORDER BY a

user1994892
04 фев. 2019, в 14:47

Поделиться

select (name||'('||UPPER(substr(occupation,1,1))||')') from occupations order by name;

select ('There are a total of '||count(name)||' '||lower(occupation)||'s.') from occupations group by occupation order by count(name), occupation;

Gopal Gupta
17 авг. 2017, в 08:14

Поделиться

select Name + '('+ substring(OCCUPATION, 1,1) +')' from OCCUPATIONS 
union  
select 'There are total ' + cast(count(OCCUPATION) as varchar) +' '+ 
lower(OCCUPATION)+'s.' from OCCUPATIONS   
group by OCCUPATION 

Hemachandra
18 май 2017, в 12:28

Поделиться

select 
  case when Occupation='Doctor' then concat(concat(concat(Name,'('),'D'),')') 
       when Occupation='Actor' then concat(concat(concat(Name,'('),'A'),')') 
       when Occupation='Professor' then concat(concat(concat(Name,'('),'P'),')')
       when Occupation='Singer' then concat(concat(concat(Name,'('),'S'),')')end as name
from OCCUPATIONS
order by name asc;

select concat(concat(concat(concat('There are a total of ',count(Occupation)),' '),lower(Occupation)),'s.')
from OCCUPATIONS
group by Occupation
order by Count(Occupation) asc,lower(Occupation); 

Anuj Sharma
21 янв. 2019, в 08:30

Поделиться

Ещё вопросы

  • 0IE8: странная граница вокруг HTML-элемента кнопки
  • 0угловая форма представить получить действие добавить ключ-пара значений
  • 1Поставщик макета устройства Android для Gmaps
  • 0Ошибка sql syntanx Я хочу сравнить две таблицы данных в одном запросе
  • 0jQuery Назад Кнопка OnLond событие?
  • 0Magento — добавить товар в корзину с пользовательским текстом
  • 1DropDownList в MVC5
  • 1группировка данных zingchart и выборка вниз
  • 1ASP.Net MVC 4 Razor — просмотр результатов поиска на веб-сетке
  • 0вложенные классы в C ++ не работают
  • 1Ява маршаллер. Использовать значение тега в качестве значения атрибута
  • 0В jquery или jquery mobile, как можно передать ссылку, созданную пользователем, на кнопку, также созданную пользователем? Под пользователем я имею в виду конечного пользователя, а не меня
  • 1Есть ли способ активировать окно с белым?
  • 0Добавить страницу перед первой страницей в TCPDF
  • 0Вернуть все строки из таблицы и добавить дополнительный столбец, чтобы указать включение сводной таблицы
  • 0Инструмент для фиксации фигурных скобок
  • 0Как передать данные между запросами в угловом ресурсе?
  • 0Вставьте UUID против UUID через триггер — Производительность
  • 0Меню jquery имеет белую рамку / фон. Как это покрасить?
  • 0Не знаю, какой плагин JQuery использовать
  • 1Пространство имен Microsoft.Contracts
  • 1Каково значение использования: string.split («»). Reverse (). Join («)?
  • 1Проблемы при векторизации TFIDF токенизированных документов?
  • 1SQLAlchemy — создать таблицу из ямла или словаря?
  • 1Как зациклить в Vue.js?
  • 1Android и область использования
  • 1Доставка тестовых параметров с помощью команды adb shell am start
  • 0JQuery отправляет HTML-сущность / эмодзи на сервер PHP
  • 0Как сослаться на значение из той же строки в MySQL?
  • 0Инкапсулированная связь и контроллер в директиве
  • 0Настроить таблицу MySQL для заказа по уникальному индексу
  • 0rror: [$ parse: синтаксис] Синтаксическая ошибка: токен ‘,’ является неожиданным токеном в столбце 84 выражения
  • 1odoo, как обновить значение одного поля, обновив значение другого, оба поля находятся в разных классах
  • 1Как я могу предотвратить смещение мяча с края экрана? простой пример KeyListenerDemo
  • 0$ rootcope часы не работают в течение очень короткого времени
  • 1Обязательное текстовое поле внутри списка в Windows Phone 7 C #
  • 1phoneGap / разработка Titanium
  • 1Android Market-подобная вкладка
  • 0Найти первый элемент в иерархии, а не в дочерних
  • 0Поймать и обработать все исключения в моем собственном классе
  • 0Codeigniter HREF с новой вкладкой
  • 1Счетчик строк в представлении индекса MVC не может генерировать число
  • 1Как бороться с конфликтами маршрутизации в WebAPI — идентификаторы строк против действия + идентификатор
  • 1Как включить переменную в запрос SQL в C # [duplicate]
  • 0Как выбрать строку с наибольшим значением в запросе с помощью SUM () и JOIN?
  • 0Показать последнее изображение из папки динамически
  • 1Инициализируйте MediaScanner в начале программы Android
  • 0Условный интервал при наличии предупреждения
  • 0Модульное тестирование углового контроллера с жасмином
  • 1Как получить текст richtextbox в текстовый блок в приложении Windows Phone?

Сообщество Overcoder

Понравилась статья? Поделить с друзьями:
  • Mysql ssl authentication error
  • Mysql source you have an error in your sql syntax
  • Mysql slave stop error
  • Mysql slave skip error
  • Mysql servicejob for mysql service failed because the control process exited with error code