Domanda

Sto cercando di eseguire una query in SQL Server 2008 su una tabella in cui alcuni dati sono stati inseriti in modo incoerente e devo gestirlo.

Esempio di dati di tabella:

OrderID   Qty   Price   MarkedUpTotal
1         10    1.00    11.00
1         -1    1.00    -1.10
1         -1    1.00    1.10

Devo gestire la situazione in cui la Qtà è negativa ma MarkedUpTotal è stato inserito come positivo.

Vorrei eseguire la seguente query:

SELECT OrderID, SUM(Qty) as OrderTotalQty, 
        SUM(Qty*Price) as InternalCost,
        CASE WHEN Qty < 0 and MarkedUpTotal > 0 
             THEN sum(-1*MarkedUpTotal) 
             ELSE SUM(MarkedUpTotal) END as ClientCost  
    FROM OrderItems 
    GROUP BY OrderID

Tuttavia, quando eseguo questa query, viene visualizzato il seguente errore:

Qtà colonna non è valido nell'elenco di selezione perché non è contenuto né in una funzione aggregata né nella clausola GROUP BY.

La colonna MarkedUpTotal non è valida nell'elenco di selezione perché non è contenuta né in una funzione aggregata né nella clausola GROUP BY.

Desidero il seguente risultato:

OrderID    OrderTotalQty   InternalCost   ClientCost
1          8               8.00           8.80

Mi sembra strano che io debba GROUP BY Qty e MarkedUpTotal quando sono usati solo in modo condizionale dall'istruzione CASE. Se rimuovo l'ultima selezione (l'istruzione CASE) la query viene eseguita correttamente e non è necessario che Qtà o Prezzo siano inclusi in GROUP BY.

Perché SQL lo richiede? Esiste un'unica query che potrebbe realizzare quanto sopra?

Attualmente sto risolvendo il problema utilizzando una tabella temporanea. Modifico MarkedUpTotal di ogni voce se necessario e quindi eseguo un semplice SUM (MarkedUpTotal) nella query principale dalla tabella temporanea.

È stato utile?

Soluzione

SELECT OrderID, SUM(Qty) as OrderTotalQty, 
        SUM(Qty*Price) as InternalCost,
        SUM(CASE WHEN Qty < 0 and MarkedUpTotal > 0 
             THEN -1*MarkedUpTotal
             ELSE MarkedUpTotal) END as ClientCost  
    FROM OrderItems 
    GROUP BY OrderID

Il motivo per cui dà l'errore è perché lo stai sommando all'interno del CASO, che restituirà 1 valore all'esterno. A SELEZIONA con GROUP BY, sembrerà che tu stia passando un valore numerico (che potrebbe essere una costante o proveniente da qualche altra fonte) come una colonna.

Pensa alla tua istruzione SQL, simile a questa

SELECT OrderID, SUM(Qty) as OrderTotalQty, 
        SUM(Qty*Price) as InternalCost,
        CASE WHEN Qty < 0 and MarkedUpTotal > 0 
             THEN 10
             ELSE 20 END as ClientCost  
    FROM OrderItems 
    GROUP BY OrderID

Ora questo sta restituendo una nuova colonna (ClientCost), che non utilizza alcuna aggregazione.
Quindi, ti chiede di usarlo nell'espressione GROUP BY.

Altri suggerimenti

Tieni presente che il risultato di un'istruzione GROUP BY o di un'istruzione in cui una o colonne utilizza una funzione aggregata ha ciascuna riga contenente un riepilogo di altre righe.

L'espressione CASE che stai usando dipende dai valori delle singole righe piuttosto che dai riepiloghi; puoi fare riferimento solo a valori non aggregati (ovvero valori a riga singola) in una funzione aggregata o nella clausola WHERE, pertanto la soluzione implicherebbe l'inserimento del CASE all'interno di una funzione aggregata, in questo caso il tuo SUM.

L'errore riguarda questa parte. Quale valore di riga Qtà deve utilizzare Sql Server?

CASE WHEN Qty < 0 and MarkedUpTotal > 0 
    THEN sum(-1*MarkedUpTotal) 
    ELSE SUM(MarkedUpTotal) 
END as ClientCost

Potresti riscriverlo come:

sum(CASE WHEN Qty < 0 and MarkedUpTotal > 0 
    THEN sum(-1*MarkedUpTotal) 
    ELSE SUM(MarkedUpTotal) 
END as ClientCost)

o

CASE WHEN sum(Qty) < 0 and sum(MarkedUpTotal) > 0 
    THEN sum(-1*MarkedUpTotal) 
    ELSE SUM(MarkedUpTotal) 
END as ClientCost

A seconda di cosa intendi :)

Fallo in questo modo:

SELECT OrderID, SUM(Qty) as OrderTotalQty, 
        SUM(Qty*Price) as InternalCost,
        sum(CASE WHEN Qty < 0 and MarkedUpTotal > 0 
             THEN -1*MarkedUpTotal 
             ELSE MarkedUpTotal END) as ClientCost  
    FROM OrderItems 
    GROUP BY OrderID
  

Mi sembra strano che debba GROUP   BY Qty e MarkedUpTotal quando sono   utilizzato solo in modo condizionale dal   Dichiarazione CASE.

Ho evidenziato l'errore di seguito:

SELECT OrderID, SUM(Qty) as OrderTotalQty, 
        SUM(Qty*Price) as InternalCost,
        CASE WHEN Qty < 0 and MarkedUpTotal > 0   -- BOOM!!!!!!
             THEN sum(-1*MarkedUpTotal) 
             ELSE SUM(MarkedUpTotal) END as ClientCost  
    FROM OrderItems 
    GROUP BY OrderID

Il server SQL non sa come valutare CASE WHEN Qty < 0 and MarkedUpTotal > 0. Nella tabella sono presenti 3 valori diversi per questi record, il che normalmente non rappresenta un problema, ma poiché si stanno raggruppando i record, l'espressione non ha senso poiché SQL Server non sa quale dei tre valori utilizzare durante la valutazione l'espressione case, quindi genera gli errori di analisi ostili all'utente visualizzati nel PO.

Tutti i suggerimenti sul codice in questo thread forniscono una soluzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top