Perché non posso usare un alias per un aggregato in una clausola having?

Il mio codice è come mostrato di seguito:

select col1,count(col2) as col7 from --some join operation group by col1 having col7 >= 3 -- replace col7 by count(col2) to make the code work 

Il mio codice causa l’errore “Nome colonna non valido ‘col7′”. Perché succede? Sembra illogico che SQL non mi permetta di usare col7 nell’ultima riga.

Sto usando SQL Server Express 2008

In MS SQL, l’unica posizione (di cui sono a conoscenza) che è ansible fare riferimento agli alias è contenuta nella clausola ORDER BY. La possibilità di fare riferimento a alias in altre parti della query è una funzionalità che molte altre piattaforms db hanno e onestamente mi infastidisce che Microsoft non l’abbia considerata una funzionalità abbastanza utile per aggiungerla.

La clausola HAVING viene valutata prima di SELECT, quindi il server non sa ancora dell’alias.

1.Prima viene creato il prodotto di tutte le tabelle nella clausola FROM.
2.La CLAUSE WHERE viene quindi valutata per eliminare le righe che non soddisfano la condizione di ricerca.
3. Avanti, le righe sono raggruppate usando le colonne in GROUP BY CLAUSE.
4. Quindi, i gruppi che non soddisfano le condizioni di ricerca nella CLAUSOLA IN CORSO sono eliminati.
5. Avanti, vengono valutate le espressioni nella lista di destinazione SELECT CLAUSE.
6.Se la parola chiave DISTINCT è presente nella clausola select, le righe duplicate vengono ora eliminate.
7. L’UNION viene acquisito dopo ogni sottoselezione viene valutata.
8.Infine, le righe risultanti vengono ordinate in base alle colonne specificate in ORDER BY CLAUSE.
9.TOP CLAUSE eseguito

Spero che questo risponda alla tua domanda !!!
Inoltre spiega perché l’alias funziona nella clausola ORDER BY.

Prova con questo in quanto l’elenco di selezione contiene la stessa espressione che puoi usare nella clausola di avere anche:

 SELECT COL1,COUNT(COL2) AS COL7 FROM --SOME JOIN OPERATION GROUP BY COL1 HAVING COUNT(COL2) >= 3 

È necessario selezionare due volte per utilizzare la colonna count ()

 select * from (select col1,count(col2) as col7 from --some join operation group by col1) as temp where temp.col7 >= 3 

U può usare questo codice:

 IF OBJECT_ID('tempdb..#temp') is not null DROP TABLE #temp -- Create tempurary table CREATE TABLE #temp (Id BIGINT IDENTITY(1,1), col1 BIGINT, countOfcol2 BIGIN) --insert from the table 2 #temp INSERT INTO #temp (col1,countOfcol2) select col1,count(col2) as col7 from --some join operation select col1,countOfcol2 from #temp group by col1 having countOfcol2 >= 3 -- replace col7 by count(col2) to make the code work 

selezionare col1, contare (col2) come col7 da –some gruppo operazione join da col1 conteggio (col2) > = 3;

Onestamente sono seccato sul perché SQL Server non elabora l’alias della colonna. Lo uso come soluzione alternativa. Stampa ancora il nome della colonna come alias, ma elabora utilizzando la funzione di aggregazione originale.

Puoi risolvere questo problema usando una query nidificata.

Ho anche incontrato questo problema quando voglio migliorare le prestazioni. Ho avuto bisogno di eseguire un count() basato su determinati campi all’interno di un campo JSON in una tabella, ovviamente vorremmo analizzare JSON solo una volta invece di dover includere un conteggio separato in una clausola where o have (specialmente uno costoso come nel mio caso).

Se col1 è un ID univoco, il modo più efficiente dal punto di vista computazionale potrebbe essere quello di nidificare il conteggio in una select separata

 select col1, innerquery.col7 from whatevertable inner join (select col1, count(col2) as col7 from whatevertable group by col1) as innerquery on innerquery.col1 = whatevertable.col1 where innerquery.col7 >= 3; 

In questo modo il conteggio viene eseguito una volta sola, creando una sorta di tabella di ricerca temporanea per riferimento dal resto della query.

Di nuovo, questo funziona solo se col1 è univoco per ogni record, che normalmente non è troppo chiedere poiché molte tabelle hanno una sorta di chiave primaria id.