Я пытаюсь решить HackerRank SQL - вопрос PADS.
Вопрос в том:
Сгенерируйте следующие два набора результатов:
Запросите упорядоченный по алфавиту список всех имен в ПРОФЕССИЯХ, сразу за которыми следует первая буква каждой профессии в скобках (т. е. заключенная в круглые скобки). Например: AnActorName(A)
, ADoctorName(D)
, AProfessorName(P)
и ASingerName(S)
.
Запросите количество вхождений каждой профессии в OCCUPATIONS. Отсортируйте вхождения в порядке возрастания и выведите их в следующем формате:
There are a total of [occupation_count] [occupation]s.
где [occupation_count]
— количество вхождений профессии в ПРОФЕССИИ, а [occupation]
— название профессии в нижнем регистре. Если несколько профессий имеют одинаковые [occupation_count]
, их следует расположить в алфавитном порядке.
Мое решение:
SELECT NAME || '(' || SUBSTR(OCCUPATION,1,1) || ')'
FROM OCCUPATIONS
ORDER BY NAME
UNION
SELECT 'There are a total of ' || COUNT(OCCUPATION) || ' ' || LOWER(OCCUPATION) || 's.'
FROM OCCUPATIONS
GROUP BY OCCUPATION
ORDER BY OCCUPATION;
OP:
ERROR at line 4:
ORA-00933: SQL command not properly ended
(It seems, we cannot use ORDER BY BEFORE UNION)
Я пересмотрел свой код на:
SELECT NAME || '(' || SUBSTR(OCCUPATION,1,1) || ')'
FROM OCCUPATIONS
UNION
SELECT 'There are a total of ' || COUNT(OCCUPATION) || ' ' || LOWER(OCCUPATION) || 's.'
FROM OCCUPATIONS
GROUP BY OCCUPATION
ORDER BY NAME, OCCUPATION;
OP:
ERROR at line 7:
ORA-00904: "NAME": invalid identifier
Пожалуйста, помогите мне здесь.
Поскольку вы хотите вывести два упорядоченных набора данных в одном запросе, самый простой способ - назначить идентификатор каждому запросу, а затем упорядочить его и столбец, который вы хотите упорядочить, например:
SELECT info
FROM (SELECT 1 qry, NAME || '(' || SUBSTR(OCCUPATION,1,1) || ')' info
FROM OCCUPATIONS
UNION ALL
SELECT 2 qry, 'There are a total of ' || COUNT(OCCUPATION) || ' ' || LOWER(OCCUPATION) || 's.' info
FROM OCCUPATIONS
GROUP BY OCCUPATION)
ORDER BY qry, info;
Обратите внимание, что, поскольку два запроса не будут возвращать одни и те же строки, я использовал UNION ALL
, поскольку UNION
выполняет DISTINCT для результирующего набора данных, а UNION ALL
— нет. Кроме того, я предполагаю, что если у вас есть два разных человека с одинаковым именем и профессией (например, разные даты рождения), вы должны вывести обе строки, а не одну строку?
Также обратите внимание, что когда у вас есть запрос UNION
/UNION ALL
, выходные столбцы наследуют имя столбца из первого запроса, поэтому ваш второй запрос выдавал вам ошибку недопустимого идентификатора (вы не дали своему столбцу псевдоним!).
Эй .. он работает нормально, спасибо за решение и объяснение. Кроме того, нужно научиться использовать идентификатор и разницу между UNION и UNION ALL :)
Я ответил на ваш вопрос о том, как упорядочить запросы UNION, но я должен сказать, что MT0 полностью верен в том смысле, что ваше решение не отвечает на вопрос, который вы отправили из hackerrank, который требует двух наборов результатов. И порядок второго запроса нуждается в настройке
Сгенерируйте следующие два набора результатов
Вы НЕ генерируете два набора результатов. Вы выполняете два SELECT
и пытаетесь объединить их в один набор результатов, используя UNION
, и это не то, о чем просит вопрос. Прекратите использовать UNION
и используйте два запроса.
Первый результирующий набор будет таким:
SELECT NAME || '(' || SUBSTR(OCCUPATION,1,1) || ')'
FROM OCCUPATIONS
ORDER BY NAME;
Второй результирующий набор будет:
SELECT 'There are a total of ' || COUNT(OCCUPATION) || ' ' || LOWER(OCCUPATION) || 's.'
FROM OCCUPATIONS
GROUP BY OCCUPATION
а затем вам нужно ORDER BY
количество вхождений И затем название профессии (которое я оставляю вам решить).
Ага... также получил вывод, используя два отдельных запроса. Спасибо! КОД: ВЫБЕРИТЕ ИМЯ || '(' || SUBSTR(OCCUPATION,1,1) || ')' FROM OCUPATION ORDER BY NAME; SELECT 'Всего ' || СЧЁТ(ПРОФЕССИЯ) || ' ' || НИЖЕ(ПРОФЕССИЯ) || 'с.' ИНФОРМАЦИЯ ОТ ПРОФЕССИЙ ГРУППА ПО ЗАНЯТИЯМ ПОРЯДОК ПО ИНФОРМАЦИИ;
@JanviChitroda Последнее предложение ORDER BY
неверно, поскольку в вопросе вас просят «Отсортировать вхождения в порядке возрастания ... [и], если несколько профессий имеют одинаковое количество занятий, они должны быть упорядочены в алфавитном порядке». Вы сортируете вхождения в алфавитном порядке (как часть строки info
), а не в возрастающем числовом порядке, и вы не включаете занятие в предложение порядка.
Я сортирую строку INFO (например: всего 3 врача, всего 4 актера). Здесь начало строки (всего ) будет одинаковым для всех записей, поэтому он будет проверять наличие количество профессий и после этого название профессии. Таким образом, он косвенно сортирует 1-е место по количеству профессий, а затем по названию профессии. Я получаю результат от этого, но я не уверен, что метод правильный, поскольку я недавно начал изучать SQL. Пожалуйста, поправьте меня, если подход неверен.
@JanviC Если вы сортируете как числа, то 1
< 2
< 12
однако, если вы сортируете как строки, то '1'
< '12'
< '2'
. Вы сортируете по INFO
, которая является (сцепленной) строкой, и она будет сортировать занятие с 12 людьми перед занятием с 2 людьми; это НЕ в порядке возрастания количества занятий. Вам нужно сортировать непосредственно по числовому значению COUNT
, а не по объединенной строке.
В общем (для всех, кто хочет знать, как упорядочить результаты UNION/INTERSECT/MINUS, вам нужно будет следовать ключевым словам
order by
с одним или несколькими именами столбцов из верхнего спискаselect
(в вашем случае есть только один столбец , поэтомуorder by NAME || '(' || SUBSTR(OCCUPATION,1,1) || ')'
, но вы также можете присвоить ему псевдоним и упорядочить по имени псевдонима), или еще один или несколько позиционных идентификаторов, относящихся к n-му столбцу, например,order by 1
для упорядочения по первому столбцу в спискеselect
.