Kolumna „nieprawidłowa na liście wyboru, ponieważ nie jest zawarta ani w funkcji agregującej, ani w klauzuli GROUP BY”

84

Chciałbym wyświetlić kolumnę Bw moim poniższym SQL, ale kiedy dodam ją do zapytania, otrzymuję następujący błąd:

Kolumna T2.B 'jest nieprawidłowa na liście wyboru, ponieważ nie jest zawarta ani w funkcji agregującej, ani w klauzuli GROUP BY.

Mój kod:

SELECT A, COUNT(B) as T1, B 
FROM T2 
WHERE ID=1 
GROUP BY A 
msvuze
źródło
2
możliwy duplikat klauzuli Group By powodujący błąd . Jeśli szukałeś tutaj swojego komunikatu o błędzie, znajdziesz tutaj wiele dopasowań, które odpowiedziałyby na to za Ciebie. Proszę przynajmniej włożyć wysiłek, aby to zrobić, a także przeczytać komunikat o błędzie, który nie tylko opisuje dokładny problem, ale także dokładnie określa, która kolumna go powoduje.
Ken White

Odpowiedzi:

152

Innymi słowy, ten błąd mówi ci, że SQL Server nie wie, który B wybrać z grupy.

Albo chcesz wybrać jedną konkretną wartość (np. MIN, SUMLub AVG), w którym to przypadku użyjesz odpowiedniej funkcji agregującej, albo chcesz wybrać każdą wartość jako nowy wiersz (tj. Uwzględniać Bna GROUP BYliście pól).


Weź pod uwagę następujące dane:

ID AB
1 1 13
1 1 79
1 2 13
1 2 13
1 2 42

Zapytanie

SELECT A, COUNT(B) AS T1 
FROM T2 
GROUP BY A

zwróci:

A T1
1 2
2 3

co jest dobre i dobre.

Jednak weź pod uwagę następujące (niedozwolone) zapytanie, które spowodowałoby ten błąd:

SELECT A, COUNT(B) AS T1, B 
FROM T2 
GROUP BY A

I zwrócony zestaw danych ilustrujący problem:

A T1 B
1 2 13? 79? Zarówno 13, jak i 79 w oddzielnych wierszach? (13 + 79 = 92)? ...?
2 3 13? 42? ...?

Jednak poniższe dwa zapytania wyjaśniają to jasno i nie spowodują błędu:

  1. Korzystanie z agregatu

    SELECT A, COUNT(B) AS T1, SUM(B) AS B
    FROM T2
    GROUP BY A
    

    zwróci:

    A T1 B
    1 2 92
    2 3 68
    
  2. Dodanie kolumny do GROUP BYlisty

    SELECT A, COUNT(B) AS T1, B
    FROM T2
    GROUP BY A, B
    

    zwróci:

    A T1 B
    1 1 13
    1 1 79
    2 2 13
    2 1 42
    
lc.
źródło
3
dzięki za to szczegółowe wyjaśnienie - naprawdę rozwiązałem niektóre z moich pytań. najtrudniejszą częścią początkowego problemu jest to, że możesz uruchomić zapytanie na jakimś optymalnym zestawie danych i nie otrzymasz tego wyjątku. ale kiedy masz zduplikowane dane dla B, otrzymasz ten wyjątek. Więc lepiej zaplanuj swoje zapytanie, korzystając z przykładów, które lc. dał z góry :)
qgicup
jaka miła odpowiedź!
Aerin
0

Konsekwencją tego jest to, że możesz potrzebować raczej szalenie wyglądającego zapytania, np.

SELECT [dbo].[tblTimeSheetExportFiles].[lngRecordID]            AS lngRecordID
          ,[dbo].[tblTimeSheetExportFiles].[vcrSourceWorkbookName]  AS vcrSourceWorkbookName
          ,[dbo].[tblTimeSheetExportFiles].[vcrImportFileName]      AS vcrImportFileName
          ,[dbo].[tblTimeSheetExportFiles].[dtmLastWriteTime]       AS dtmLastWriteTime
          ,[dbo].[tblTimeSheetExportFiles].[lngNRecords]            AS lngNRecords
          ,[dbo].[tblTimeSheetExportFiles].[lngSizeOnDisk]          AS lngSizeOnDisk
          ,[dbo].[tblTimeSheetExportFiles].[lngLastIdentity]        AS lngLastIdentity
          ,[dbo].[tblTimeSheetExportFiles].[dtmImportCompletedTime] AS dtmImportCompletedTime
          ,MIN ( [tblTimeRecords].[dtmActivity_Date] )              AS dtmPeriodFirstWorkDate
          ,MAX ( [tblTimeRecords].[dtmActivity_Date] )              AS dtmPeriodLastWorkDate
          ,SUM ( [tblTimeRecords].[decMan_Hours_Actual] )           AS decHoursWorked
          ,SUM ( [tblTimeRecords].[decAdjusted_Hours] )             AS decHoursBilled
      FROM [dbo].[tblTimeSheetExportFiles]
      LEFT JOIN   [dbo].[tblTimeRecords]
              ON  [dbo].[tblTimeSheetExportFiles].[lngRecordID] = [dbo].[tblTimeRecords].[lngTimeSheetExportFile]
        GROUP BY  [dbo].[tblTimeSheetExportFiles].[lngRecordID]
                 ,[dbo].[tblTimeSheetExportFiles].[vcrSourceWorkbookName]
                 ,[dbo].[tblTimeSheetExportFiles].[vcrImportFileName]
                 ,[dbo].[tblTimeSheetExportFiles].[dtmLastWriteTime]
                 ,[dbo].[tblTimeSheetExportFiles].[lngNRecords]
                 ,[dbo].[tblTimeSheetExportFiles].[lngSizeOnDisk]
                 ,[dbo].[tblTimeSheetExportFiles].[lngLastIdentity]
                 ,[dbo].[tblTimeSheetExportFiles].[dtmImportCompletedTime]

Ponieważ tabela podstawowa jest tabelą podsumowań, jej klucz podstawowy obsługuje jedyne grupowanie lub porządkowanie, które jest naprawdę konieczne. W związku z tym klauzula GROUP BY istnieje wyłącznie w celu zaspokojenia parsera zapytań.

David A. Gray
źródło
0

Możesz użyć przypadku w aktualizacji i zamienić tyle, ile chcesz

update Table SET column=(case when is_row_1 then value_2 else value_1 end) where rule_to_match_swap_columns
Viswanath Lekshmanan
źródło