Действительно ли эти два запроса являются тем же - GROUP BY по сравнению с Отличным?

Эти два запроса, кажется, возвращают те же результаты. Это случайно, или они - действительно то же?

1.

SELECT t.ItemNumber,
  (SELECT TOP 1 ItemDescription
   FROM Transactions
   WHERE ItemNumber = t.ItemNumber
   ORDER BY DateCreated DESC) AS ItemDescription
FROM Transactions t
GROUP BY t.ItemNumber

2.

SELECT DISTINCT(t.ItemNumber),
  (SELECT TOP 1 ItemDescription
   FROM Transactions
   WHERE ItemNumber = t.ItemNumber
   ORDER BY DateCreated DESC) AS ItemDescription
FROM Transactions t

Немного объяснения: я пытаюсь получить отличный список объектов от таблицы, полной транзакций. Для каждого объекта я ищу ItemNumber (поле идентификации) и новый ItemDescription.

7
задан Joe Stefanelli 28 July 2010 в 15:29
поделиться

8 ответов

В вашем примере №2 я некоторое время почесал голову - я подумал: «Вы не можете ОТЛИЧИТЬ один столбец, что бы это значило?» - пока я не понял, что происходит.

Когда у вас есть

SELECT DISTINCT(t.ItemNumber)

, вы не , несмотря на внешность, на самом деле запрашиваете различные значения из t.ItemNumber ! Ваш пример №2 фактически анализируется так же, как

SELECT DISTINCT
  (t.ItemNumber)
  ,
  (SELECT TOP 1 ItemDescription
   FROM Transactions
   WHERE ItemNumber = t.ItemNumber
   ORDER BY DateCreated DESC) AS ItemDescription
FROM Transactions t

, с синтаксически правильными, но лишними круглыми скобками вокруг t.ItemNumber . DISTINCT применяется к набору результатов в целом.

В этом случае, поскольку ваша GROUP BY группирует по столбцу, который фактически изменяется, вы получите те же результаты.На самом деле я немного удивлен, что SQL Server (в примере GROUP BY ) не настаивает на том, чтобы столбец с подзапросом упоминался в списке GROUP BY .

5
ответ дан 6 December 2019 в 08:41
поделиться

Если вы используете по крайней мере 2005 год и можете использовать CTE , это немного чище, ИМХО.

РЕДАКТИРОВАТЬ: Как указано в ответе Мартина , это также работает намного лучше.

;with cteMaxDate as (
    select t.ItemNumber, max(DateCreated) as MaxDate
        from Transactions t
        group by t.ItemNumber
)
SELECT t.ItemNumber, t.ItemDescription
    FROM cteMaxDate md
        inner join Transactions t
            on md.ItemNumber = t.ItemNumber
                and md.MaxDate = t.DateCreated
3
ответ дан 6 December 2019 в 08:41
поделиться

Поскольку вы не используете какие-либо агрегатные функции, SQL Server должен быть достаточно умен, чтобы рассматривать GROUP BY как a ОТЛИЧИТЕЛЬНЫЙ .

Возможно, вас заинтересует следующий пост Stack Overflow для дальнейшего чтения по этой теме:

2
ответ дан 6 December 2019 в 08:41
поделиться

GROUP BY необходим для правильного возврата результатов при использовании агрегатных функций в запросе sql. Поскольку вы не используете агрегатную функцию, нет необходимости в GROUP BY , и, следовательно, запросы такие же.

1
ответ дан 6 December 2019 в 08:41
поделиться

Да, они вернут те же результаты.

2
ответ дан 6 December 2019 в 08:41
поделиться

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

Оба были выбиты из поля зрения ROW_NUMBER, хотя...

with T as
(
SELECT ItemNumber, 
       ItemDescription,
       ROW_NUMBER() OVER ( PARTITION BY ItemNumber ORDER BY DateCreated DESC) AS RN
FROM Transactions
)
SELECT * FROM T
WHERE RN=1

edit ...который в свою очередь был побежден решением Джо на моей тестовой установке.

Plans

Test Setup

CREATE TABLE Transactions
(
ItemNumber INT not null,
ItemDescription VARCHAR(50) not null,
DateCreated DATETIME not null
)

INSERT INTO Transactions
SELECT 
number, NEWID(),DATEADD(day, cast(rand(CAST(newid() as varbinary))*10000 
  as int),getdate()) 
FROM master.dbo.spt_values

ALTER TABLE dbo.Transactions ADD CONSTRAINT
    PK_Transactions PRIMARY KEY CLUSTERED 
    (ItemNumber,DateCreated) 
4
ответ дан 6 December 2019 в 08:41
поделиться

Основываясь на данных и простых запросах, обе программы вернут одинаковые результаты. Однако фундаментальные операции сильно отличаются.

DISTINCT, как опередил меня AakashM, применяется к всем значениям столбцов, включая значения из подвыборок и вычисляемых столбцов. Все, что делает DISTINCT - это удаляет дубликаты, основанные на всех задействованных столбцах, из видимости. Вот почему его принято считать хаком, потому что люди используют его для избавления от дубликатов, не понимая, почему запрос возвращает их в первую очередь (потому что они должны использовать IN или EXISTS, а не объединение, как правило). PostgreSQL - единственная известная мне база данных с предложением DISTINCT ON, которое работает так, как, вероятно, и предполагал ОП.

Предложение GROUP BY отличается - его основное назначение заключается в группировке для точного использования агрегатной функции. Чтобы обеспечить эту функцию, значения столбцов будут уникальными значениями на основе того, что определено в предложении GROUP BY. В этом запросе никогда не понадобится DISTINCT, потому что интересующие значения уже уникальны.

Заключение

Это плохой пример, потому что он представляет DISTINCT и GROUP BY как равнозначные, хотя это не так.

3
ответ дан 6 December 2019 в 08:41
поделиться

Да, они возвращают те же результаты.

Обычно предложение group by (найдено здесь ) группирует строки по указанному столбцу, поэтому, если у вас есть сумма в вашем операторе select. Таким образом, если у вас есть таблица вроде:

O_Id        OrderDate   OrderPrice      Customer
1           2008/11/12  1000            Hansen
2           2008/10/23  1600            Nilsen
3           2008/09/02  700             Hansen
4           2008/09/03  300             Hansen
5           2008/08/30  2000            Jensen
6           2008/10/04  100             Nilsen

Если вы группируете по покупателям и запрашиваете сумму или цену заказа, вы получите

Customer    SUM(OrderPrice)
Hansen          2000
Nilsen             1700
Jensen          2000

В отличие от этого, отдельная (найденная здесь ) просто делает это так. у вас нет повторяющихся строк. В этом случае исходная таблица останется прежней, поскольку каждая строка отличается от других.

1
ответ дан 6 December 2019 в 08:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: