Ordinamento query (prima positivi, poi negativi).

martedì 05 gennaio 2010 - 15.39

autosblindo Profilo | Newbie

Ciao,

ho questa tabella:

CREATE TABLE [dbo].[SAN_CRT_DOCUMENTI]( [Id] [bigint] IDENTITY(1,1) NOT NULL, [SessionId] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [IdTesta] [decimal](10, 0) NOT NULL, [IdRiga] [int] NOT NULL, [Posizione] [int] NOT NULL, CONSTRAINT [PK_SAN_CRT_DOCUMENTI] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY]

Popolo la tabella con dati di esempio:
INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 100, 1, 1) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 100, 2, -2) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 100, 2, -1) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 100, 2, 1) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 100, 2, 2) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 100, 2, 3) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 101, 1, -2) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 101, 1, -1) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 101, 1, 1) INSERT INTO SAN_CRT_DOCUMENTI(SessionId, IdTesta, IdRiga, Posizione) VALUES ('0123456789', 101, 1, 2)

Query di selezione:
SELECT SessionId, IdTesta, IdRiga, Posizione FROM SAN_CRT_DOCUMENTI ORDER BY IdTesta, IdRiga, Posizione

Risultato:
0123456789 100 1 1
0123456789 100 2 -2
0123456789 100 2 -1
0123456789 100 2 1
0123456789 100 2 2
0123456789 100 2 3
0123456789 101 1 -2
0123456789 101 1 -1
0123456789 101 1 1
0123456789 101 1 2

Quello che vorrei ottenere è un ordinamento diverso da quanto ottenuto. Vorrei mantenere l'ordinamento per IdTesta e IdRiga, e aggiungere l'ordinamento per Posizione in modo da avere prima tutti i numeri positivi (1, 2, 3) e poi quelli negativi (-1, -2, -3).
Per intenderci il risultato della select dovrebbe essere questo:

0123456789 100 1 1
0123456789 100 2 1
0123456789 100 2 2
0123456789 100 2 3
0123456789 100 2 -1
0123456789 100 2 -2
0123456789 101 1 1
0123456789 101 1 2
0123456789 101 1 -1
0123456789 101 1 -2

Ho già fatto alcuni tentativi, come creare in select un campo extra (PosizioneOrdinamento) che facevo diventare Z + il numero * -1 quando il campo Posizone era negativo, ma in questo modo il campo diventa testuale e l'ordinamento non è più corretto.
Potrei utilizzare un numero alto da sommare al numero negativo reso positivo. In questo modo funziona, ma non credo sia la soluzione migliore.

Attendo quindi un vostro consiglio, e ringrazio in anticipo.

Carlo.

lbenaglia Profilo | Guru

>Per intenderci il risultato della select dovrebbe essere questo:
>
>0123456789 100 1 1
>0123456789 100 2 1
>0123456789 100 2 2
>0123456789 100 2 3
>0123456789 100 2 -1
>0123456789 100 2 -2
>0123456789 101 1 1
>0123456789 101 1 2
>0123456789 101 1 -1
>0123456789 101 1 -2

Ciao Carlo,

Supponendo di avere al più 10 posizioni potresti utilizzare una query simile a:

SELECT SessionId, IdTesta, IdRiga, Posizione FROM dbo.SAN_CRT_DOCUMENTI ORDER BY IdTesta, IdRiga, CASE WHEN Posizione < 0 THEN Posizione * -10 END; /* Output: SessionId IdTesta IdRiga Posizione ----------- -------- ----------- ----------- 0123456789 100 1 1 0123456789 100 2 1 0123456789 100 2 2 0123456789 100 2 3 0123456789 100 2 -1 0123456789 100 2 -2 0123456789 101 1 1 0123456789 101 1 2 0123456789 101 1 -1 0123456789 101 1 -2 (10 row(s) affected) */

>Potrei utilizzare un numero alto da sommare al numero negativo
>reso positivo. In questo modo funziona, ma non credo sia la soluzione
>migliore.
Eh si, è simile a quella proposta ma non è che ci siano molte alternative

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

autosblindo Profilo | Newbie

Ciao Lorenzo,

grazie per la celere risposta. Leggendola mi si è accesa una lampadina, e credo di aver risolto il problema, ma vorrei avere un tuo parare.
Ho così trasformato la select:
SELECT SessionId, IdTesta, IdRiga, Posizione, (CASE WHEN Posizione < 0 THEN (SELECT MAX(TEMP_SAN_CRT_DOCUMENTI.Posizione) FROM SAN_CRT_DOCUMENTI TEMP_SAN_CRT_DOCUMENTI WHERE TEMP_SAN_CRT_DOCUMENTI.IdTesta = SAN_CRT_DOCUMENTI.IdTesta AND TEMP_SAN_CRT_DOCUMENTI.IdRiga = SAN_CRT_DOCUMENTI.IdRiga AND TEMP_SAN_CRT_DOCUMENTI.SessionId = '444780736') + Posizione*-1 ELSE Posizione END) AS PosizioneOrdinamento FROM SAN_CRT_DOCUMENTI ORDER BY SAN_CRT_DOCUMENTI.SessionId, SAN_CRT_DOCUMENTI.IdTesta, SAN_CRT_DOCUMENTI.IdRiga, SAN_CRT_DOCUMENTI.PosizioneOrdinamento

In buona sostanza cerco il numero di posizione maggiore dato IdTesta, IdRiga e SessionId, e lo sommo a Posizione reso positivo quando posizione è negativo.
In questo modo ottengo questo risultato:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Grazie, Carlo.

lbenaglia Profilo | Guru

>Ciao Lorenzo,
>
>grazie per la celere risposta. Leggendola mi si è accesa una
>lampadina, e credo di aver risolto il problema, ma vorrei avere
>un tuo parare.
>Ho così trasformato la select:
>SELECT SessionId, IdTesta, IdRiga, Posizione,
>(CASE
> WHEN Posizione < 0 THEN
> (SELECT MAX(TEMP_SAN_CRT_DOCUMENTI.Posizione)
>FROM SAN_CRT_DOCUMENTI TEMP_SAN_CRT_DOCUMENTI
>WHERE TEMP_SAN_CRT_DOCUMENTI.IdTesta = SAN_CRT_DOCUMENTI.IdTesta
>AND TEMP_SAN_CRT_DOCUMENTI.IdRiga = SAN_CRT_DOCUMENTI.IdRiga
>AND TEMP_SAN_CRT_DOCUMENTI.SessionId = '444780736') + Posizione*-1
> ELSE
> Posizione
>END) AS PosizioneOrdinamento
>FROM SAN_CRT_DOCUMENTI
>ORDER BY SAN_CRT_DOCUMENTI.SessionId, SAN_CRT_DOCUMENTI.IdTesta,
>SAN_CRT_DOCUMENTI.IdRiga, SAN_CRT_DOCUMENTI.PosizioneOrdinamento
>
>In buona sostanza cerco il numero di posizione maggiore dato
>IdTesta, IdRiga e SessionId, e lo sommo a Posizione reso positivo
>quando posizione è negativo.

Secondo me non è il caso di eseguire una query correlata.
Quante sono le posizioni per session, testa e riga? 10, 100, 1000?
Poco male, modifica il fattore moltiplicativo nella precedente query.

>Grazie, Carlo.
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org

autosblindo Profilo | Newbie

La condizione iniziale è che per un IdTesta e un IdRiga esista sempre e solo una Posizione. Le ulteriori posizioni che vengono create, sempre negative, sono duplicati di IdTesta e IdRiga. Difficilmente si potranno avere più di 10 duplicati. Quindi, utilizzando la select che mi hai proposto, se moltiplico per -100 posso stare tranquillo.

Solo una curiosità, perchè mi sconsigli l'uso della query correlata?

Grazie ancora.

Carlo.

lbenaglia Profilo | Guru

>Solo una curiosità, perchè mi sconsigli l'uso della query correlata?
Perché è più pesante

>Grazie ancora.
Prego.

Ciao!
--
Lorenzo Benaglia
Microsoft MVP - SQL Server
http://blogs.dotnethell.it/lorenzo/
http://italy.mvps.org
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2017
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5