2013-01-01 64 views
14

qualcuno può spiegare perché non possiamo usare le funzioni finestrate in group by clausola e perché è consentito solo in SELECT e ORDER BYfunzioni finestrato possono essere visualizzati solo nella SELECT o clausole ORDER BY

stavo cercando di raggruppare i record in base su row_number() e una colonna in SQL Server come in questo modo:

SELECT Invoice 
from table1 
group by row_number() over(order by Invoice),Invoice 

sto ottenendo un errore

funzioni finestrato possono essere visualizzati solo nella SELECT o ORDER BY

posso selezionare questo row_number() nella clausola SELECT ma voglio sapere perché non possiamo usare GROUP BY?

+3

Qual è il punto di raggruppamento con un 'row_number()'? Ogni oggetto sarà in un gruppo da solo. La domanda è abbastanza legittima, però. – dasblinkenlight

+0

le cose è da considerare se ho una fattura doppia, in tal caso vorrei tenerlo anche questo. Puoi pensare allora perché dovrei raggruppare. il fatto è che voglio perché è così? Perché non possiamo usare le funzioni con finestra in gruppo da? – Mari

+0

come creerà ambiguità. Puoi spiegare? Nel caso in cui voglio solo selezionare il valore di classifica 2 nella clausola where. Hw creerà ambiguità – Mari

risposta

14

funzioni finestrato sono definite nelle specifiche ANSI per eseguire logicamente dopo l'elaborazione di GROUP BY, HAVING, WHERE.

Per essere più specifici sono ammessi ai passaggi 5.1 e 6 nello Logical Query Processing flow chart here.

suppongo che avrebbe potuto definire in un altro modo e ha permesso GROUP BY, WHERE, HAVING utilizzare le funzioni della finestra con la finestra è il risultato logico impostato all'inizio di quella fase, ma supponiamo che avevano e ci hanno permesso di creare query tali come

SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect 
    FROM YourTable 
    WHERE NTILE(2) OVER (PARTITION BY a ORDER BY b) > 1 
    GROUP BY a, 
      b, 
      NTILE(2) OVER (PARTITION BY a ORDER BY b) 
    HAVING NTILE(2) OVER (PARTITION BY a ORDER BY b) = 1 

Con quattro diverse finestre logici in gioco buona fortuna lavorare fuori ciò che il risultato di questo sarebbe! Inoltre, cosa succede se nello HAVING si desidera effettivamente filtrare in base all'espressione dal livello GROUP BY anziché utilizzare la finestra di righe come risultato dopo lo GROUP BY?

La versione CTE è più dettagliata ma anche più esplicita e più facile da seguire.

WITH T1 AS 
(
SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForWhere 
    FROM YourTable 
), T2 AS 
(
SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForGroupBy 
FROM T1 
WHERE NtileForWhere > 1 
), T3 AS 
(
SELECT a, 
     b, 
     NtileForGroupBy, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForHaving 
FROM T2 
GROUP BY a,b, NtileForGroupBy 
) 
SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect 
FROM T3 
WHERE NtileForHaving = 1 

Mentre questi sono tutti definiti nella dichiarazione SELECT e hanno alias è facilmente realizzabile per disambiguare risultati da diversi livelli esempio semplicemente passando da WHERE NtileForHaving = 1 a NtileForGroupBy = 1

+0

Il diagramma di flusso per l'elaborazione di una query logica è stato molto istruttivo. grazie @Martin e la tua spiegazione parla molto e ha senso :) – Mari

+0

ora il diagramma di flusso Logical Query Processing..LINK è rotto – HaveNoDisplayName

+0

@HaveNoDisplayName Se cerchi '" Logical Query Processing Poster "filetype: pdf' sembra un po ' le persone hanno fatto delle copie. –

12

è possibile aggirare che ponendo la funzione di finestra in una sottoquery:

select invoice 
,  rn 
from (
     select Invoice 
     ,  row_number() over(order by Invoice) as rn 
     from Table1 
     ) as SubQueryAlias 
group by 
     invoice 
,  rn 
+0

Sì fratello. Lo so e la mia preoccupazione è perché non possiamo usarlo all'interno di una query? Perché è stato progettato in questo modo? – Mari

+0

Bene, SQL Server non è nemmeno in grado di analizzare semplici alias nella clausola 'where'. Ad esempio, questo non funzionerà: 'selezionare datediff (day, col1, col2) come ddiff da YourTable dove ddiff> 1'. Presumo che si tratti di una sorta di limitazione del loro parser. – Andomar

+0

hmm non l'ho mai saputo. Grazie per il tuo chiarimento su questo :) – Mari

Problemi correlati