Ответ 1
Вы передаете выражение, которое хотите сгруппировать, а не псевдоним
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
Я пытаюсь выполнить группу по действию на столбце с псевдонимом (пример ниже), но не может определить правильный синтаксис.
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY 'FullName'
Каков правильный синтаксис?
Продолжая вопрос (я не ожидал, что ответы, полученные мной), будет ли решение по-прежнему применяться для столбца с псевдонимом CASEed?
SELECT
CASE
WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS 'FullName'
FROM customers
GROUP BY
LastName, FirstName
И ответ да, он все еще применяется.
Вы передаете выражение, которое хотите сгруппировать, а не псевдоним
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
Это то, что я делаю.
SELECT FullName
FROM
(
SELECT LastName + ', ' + FirstName AS FullName
FROM customers
) as sub
GROUP BY FullName
Этот метод применяется прямо к сценарию "редактирования":
SELECT FullName
FROM
(
SELECT
CASE
WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS FullName
FROM customers
) as sub
GROUP BY FullName
К сожалению, вы не можете ссылаться на свой псевдоним в выражении GROUP BY, вам придется снова написать логику, удивительную, как кажется.
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
В качестве альтернативы вы можете поместить выбор в подзапрос или общее табличное выражение, после чего вы можете группировать имя столбца (уже не псевдоним.)
Извините, это невозможно в MS SQL Server (возможно, хотя с PostgreSQL):
select lastname + ', ' + firstname as fullname
from person
group by fullname
В противном случае просто используйте это:
select x.fullname
from
(
select lastname + ', ' + firstname as fullname
from person
) as x
group by x.fullname
Или это:
select lastname + ', ' + firstname as fullname
from person
group by lastname, firstname -- no need to put the ', '
Вышеуказанный запрос выполняется быстрее, сначала группирует поля, затем вычисляет эти поля.
Следующий запрос медленнее (он пытается вычислить сначала выражение select, а затем группирует записи на основе этого вычисления).
select lastname + ', ' + firstname as fullname
from person
group by lastname + ', ' + firstname
Мое предположение:
SELECT LastName + ', ' + FirstName AS 'FullName'
FROM customers
GROUP BY LastName + ', ' + FirstName
Oracle имеет аналогичное ограничение, что раздражает. Мне любопытно, есть ли лучшее решение.
Чтобы ответить на вторую половину вопроса, это ограничение распространяется и на более сложные выражения, такие как ваш оператор case. Лучшее предложение, которое я видел, чтобы использовать суб-выбор, чтобы назвать сложное выражение.
Учитывая ваше отредактированное описание проблемы, я бы предложил использовать COALESCE()
вместо этого громоздкого выражения CASE
:
SELECT FullName
FROM (
SELECT COALESCE(LastName+', '+FirstName, FirstName) AS FullName
FROM customers
) c
GROUP BY FullName;
В старом FoxPro (я не использовал его с версии 2.5), вы могли бы написать что-то вроде этого:
SELECT LastName + ', ' + FirstName AS 'FullName', Birthday, Title
FROM customers
GROUP BY 1,3,2
Мне очень понравился этот синтаксис. Почему это не реализовано нигде? Это хороший ярлык, но я полагаю, что это вызывает другие проблемы?
SELECT
CASE
WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS 'FullName'
FROM
customers
GROUP BY
LastName,
FirstName
Это работает, потому что используемая вами формула (оператор CASE) никогда не может дать один и тот же ответ для двух разных входов.
Это не тот случай, если вы использовали что-то вроде:
LEFT(FirstName, 1) + ' ' + LastName
В таком случае "Джеймс Тейлор" и "Джон Тейлор" оба приведут к "J Taylor" .
Если вы хотите, чтобы ваш результат имел "J Taylor" дважды (по одному для каждого человека):
GROUP BY LastName, FirstName
Если, однако, вам нужна только одна строка "J Taylor" , которую вы хотите:
GROUP BY LastName, LEFT(FirstName, 1)
Если вы хотите избежать беспорядка оператора case в вашем запросе дважды, вы можете поместить его в пользовательскую функцию.
Извините, но SQL Server не будет отображать набор данных перед предложением Group By, поэтому псевдоним столбца недоступен. Вы можете использовать его в Order By.
SELECT
CASE WHEN LastName IS NULL THEN FirstName
WHEN LastName IS NOT NULL THEN LastName + ', ' + FirstName
END AS 'FullName'
FROM customers GROUP BY 1`
Для тех, кто обнаруживает себя со следующей проблемой (группировка путем обеспечения нулевого и нулевого значений рассматривается как равные)...
SELECT AccountNumber, Amount AS MyAlias
FROM Transactions
GROUP BY AccountNumber, ISNULL(Amount, 0)
(I.e. SQL Server жалуется, что вы не включили поле "Сумма" в функцию "Группировать по" или "заполнить" )
... не забудьте разместить ту же самую функцию в вашем SELECT...
SELECT AccountNumber, ISNULL(Amount, 0) AS MyAlias
FROM Transactions
GROUP BY AccountNumber, ISNULL(Amount, 0)
Вы можете использовать CROSS APPLY
для создания псевдонима и использовать его в предложении GROUP BY
, например:
SELECT FullName
FROM Customers
CROSS APPLY (SELECT LastName + ', ' + FirstName AS FullName) Alias
GROUP BY FullName