#sql #sql-server #database #database-design
#sql #sql-сервер #База данных #база данных-дизайн
Вопрос:
SELECT COALESCE (rsu.last_name ', ' rsu.first_name ' ' rsu.middle_name '.', rsu.last_name ', ' rsu.first_name) as student_name, rsu.day_id
FROM roster_school_unattended rsu
GROUP BY student_name
ORDER BY rsu.day_id
не работает. Какой самый элегантный обходной путь?
РЕДАКТИРОВАТЬ: Результирующий набор должен иметь что-то вроде этого
Muster, Hans | 2011-11-01
Muster, Hans | 2011-11-02
Williams, Clay | 2011-10-01
Williams, Clay | 2011-10-02
Сначала имя группируется по, затем для каждого имени выполняется сортировка по датам.
Комментарии:
1. Вам нужно перестать думать в терминах «элегантный», когда вы запрашиваете базу данных. Часто наименее элегантный код является лучшим с точки зрения производительности базы данных, что гораздо важнее, чем «элегантность». Вы никогда не ошибетесь, написав код базы данных с точки зрения производительности (то, что, скорее всего, будет работать наилучшим образом) в первую очередь. Как только вы привыкнете к наиболее производительному типу SQL для вашей базы данных, его будет так же легко поддерживать, как и «элегантный» код.
2. Если вы намерены часто группировать имена вместе таким образом, я считаю, что лучше всего сделать это постоянным вычисляемым столбцом. Таким образом, вам не придется выполнять все эти неприятные действия по объединению и конкатенации более одного раза.
3. Кроме того, ваша правка показывает, что вам не нужна GROUP BY . Вы имеете в виду, что хотите, чтобы все было упорядочено по столбцу name, а затем по столбцу date.
Ответ №1:
Выполнение дополнительного выбора позволит вам избежать необходимости вводить его дважды:
select t.student_name, t.day_id
from (
select COALESCE (rsu.last_name ', ' rsu.first_name ' ' rsu.middle_name '.', rsu.last_name ', ' rsu.first_name) as student_name,
rsu.day_id
from roster_school_unattended rsu ) t
group by t.student_name
order by t.day_id
Но у вас все еще есть проблема с идентификатором day_id — он не включен в ваше предложение группировки, поэтому вы не сможете выбрать его без использования aggregate (например, MAX).
Ответ №2:
Вы можете использовать подзапрос:
select student_name, day_id
from (SELECT COALESCE (rsu.last_name ', ' rsu.first_name ' ' rsu.middle_name '.', rsu.last_name ', ' rsu.first_name) as student_name, rsu.day_id
FROM roster_school_unattended rsu
) as rows
GROUP BY student_name
ORDER BY day_id
Ответ №3:
РЕДАКТИРОВАТЬ: Все заменено, поскольку недавнее редактирование вопроса показывает, что GROUP BY не требуется…
Без каких-либо изменений для «элегантности»…
SELECT
rsu.last_name ', ' rsu.first_name COALESCE (' ' rsu.middle_name '.', '') as student_name,
rsu.day_id
FROM
roster_school_unattended AS [rsu]
ORDER BY
rsu.last_name ', ' rsu.first_name COALESCE (' ' rsu.middle_name '.', ''),
rsu.day_id
Возможно изменение для «элегантности»…
WITH formatted_rsu AS
(
SELECT rsu.last_name ', ' rsu.first_name COALESCE (' ' rsu.middle_name '.', '') as student_name, rsu.day_id
FROM roster_school_unattended AS [rsu]
)
SELECT student_name, day_id
FROM formatted_rus
ORDER BY student_name, day_id
Другое возможное использование APPLY…
SELECT formatted_rsu.student_name, rsu.day_id
FROM roster_school_unattended AS [rsu]
CROSS APPLY (SELECT rsu.last_name ', ' rsu.first_name COALESCE (' ' rsu.middle_name '.', '') as student_name) AS [formatted_rsu]
ORDER BY formatted_rsu.student_name, rsu.day_id
Ответ №4:
Я бы пошел с:
SELECT
rsu.last_name
', ' rsu.first_name
COALESCE ( ' ' rsu.middle_name '.'
, ''
)
AS student_name
, rsu.day_id
FROM
roster_school_unattended AS rsu
ORDER BY
rsu.last_name
, rsu.first_name
, rsu.middle_name
, rsu.day_id
Ответ №5:
CROSS APPLY
ваш друг по псевдонимированию неоконных выражений:
SELECT this.student_name, MAX(rsu.day_id) AS day_id
FROM roster_school_unattended rsu
CROSS APPLY (
SELECT COALESCE (
rsu.last_name ', ' rsu.first_name ' ' rsu.middle_name '.'
, rsu.last_name ', ' rsu.first_name
) AS student_name
) this
GROUP BY this.student_name
ORDER BY this.student_name, MAX(rsu.day_id)
(предполагается, что SQL2005 и выше).