Клаузата GROUP BY вижда всички полета VARCHAR като различни

Станах свидетел на странно поведение, докато се опитвах да ГРУПИРАМ ПО поле VARCHAR.

Нека следният пример, където се опитвам да открия клиенти, които са сменили името си поне веднъж в миналото.

CREATE TABLE #CustomersHistory
(
Id INT IDENTITY(1,1),
CustomerId INT,
Name VARCHAR(200)
)

INSERT INTO #CustomersHistory VALUES (12, 'AAA')
INSERT INTO #CustomersHistory VALUES (12, 'AAA')
INSERT INTO #CustomersHistory VALUES (12, 'BBB')
INSERT INTO #CustomersHistory VALUES (44, '444')

SELECT ch.CustomerId, count(ch.Name) AS cnt
  FROM #CustomersHistory ch
  GROUP BY ch.CustomerId  HAVING  count(ch.Name) != 1

Което странно дава (сякаш "AAA" от първия INSERT е различен от втория)

CustomerId  cnt  //  (I was expecting)
12          3    //   2
44          1    //   1
  • Това поведение специфично за T-SQL ли е?
  • Защо се държи по този доста контраинтуитивен начин?
  • Как е обичайно да се преодолее това ограничение?

Забележка: Този въпрос е много подобен на проблем GROUP BY с varchar, където не намерих отговора на Защо

Странична бележка: Добра практика ли е да използвате HAVING count(ch.Name) != 1 вместо HAVING count(ch.Name) > 1?


person PPC    schedule 04.02.2013    source източник
comment
За да коментираме › 1 срещу != 1, в много случаи (макар и не непременно вашите) е възможно count() да бъде 0 (нулевите стойности се игнорират, например.), но 0 != 1 и следователно възможност за някои неочаквани поведение. Просто ми е навик.   -  person Code Magician    schedule 04.02.2013
comment
Ще направя собствено проучване на тази странична бележка и евентуално ще задам нов въпрос. Благодаря отново   -  person PPC    schedule 04.02.2013


Отговори (1)


Операторът COUNT() ще преброи всички редове, независимо от стойността. Мисля, че може да искате да използвате COUNT(DISTINCT ch.Name), което ще брои само уникални имена.

SELECT ch.CustomerId, count(DISTINCT ch.Name) AS cnt
  FROM #CustomersHistory ch
  GROUP BY ch.CustomerId  HAVING  count(DISTINCT ch.Name) > 1

За повече информация разгледайте статията COUNT() за книгата на линия

person Code Magician    schedule 04.02.2013
comment
Радвам се, че можах да помогна, благодаря! - person Code Magician; 04.02.2013