2016-03-16 30 views
5

Ho una vista sql, chiamiamola SampleView, i cui risultati hanno il seguente formato.gruppo tsql per ottenere il valore della colonna alfanumerica con lunghezza massima

Id (INT), NameA (VARVHAR(50)), NameB (VARCHAR(50)), ValueA (INT), ValueB (INT) 

Il set di risultati della visualizzazione contiene righe che possono avere lo stesso Id o meno. Quando ci sono due o più file con lo stesso ID, vorrei ottenere qualcosa di simile al seguente

SELECT 
    Id, 
    MAX(NameA), 
    MAX(NameB), 
    MAX(ValueA), 
    MAX(ValueB) 
FROM SampleView 
GROUP BY Id 
ORDER BY Id 

Per quanto riguarda le colonne Id, ValueA e ValueB non c'è alcun problema. D'altra parte usando MAX per entrambi NameA e NameB le cose non sono come previsto. Dopo alcuni googling e ricerche mi sono reso conto che MAX non ha il comportamento "previsto" per le colonne alfanumeriche. Dire il previsto, voglio dire usando MAX nel mio caso, sarebbe quello di restituire il valore di NameA con il numero massimo di caratteri, MAX(LEN(NameA)). Devo dire qui che non esiste alcuna possibilità per NameA di avere due valori per lo stesso Id con la stessa lunghezza. Ciò potrebbe rendere il problema più facile da risolvere.

Utilizzo SQL Server 2012 e TSQL.

Avete qualche suggerimento su come potrei affrontare questo problema?

Grazie mille in anticipo per qualsiasi aiuto.

risposta

2

È possibile utilizzare funzioni finestra:

SELECT DISTINCT 
     id, 
     FIRST_VALUE(NameA) OVER (PARTITION BY id 
           ORDER BY len(NameA) DESC) AS MaxNameA, 
     MAX(ValueA) OVER (PARTITION BY id) AS MaxValueA, 
     FIRST_VALUE(NameB) OVER (PARTITION BY id 
           ORDER BY len(NameB) DESC) AS MaxNameB, 
     MAX(ValueB) OVER (PARTITION BY id) AS MaxValueB  
FROM SampleView 

Demo here

+0

Grazie mille! È quello che voglio :) – Christos

2

È possibile utilizzare le query correlate in questo modo:

SELECT 
    t.Id, 
    (SELECT TOP 1 s.NameA FROM SampleView s 
    WHERE s.id = t.id 
    ORDER BY length(s.NameA) DESC) as NameA, 
    (SELECT TOP 1 s.NameB FROM SampleView s 
    WHERE s.id = t.id 
    ORDER BY length(s.NameB) DESC) as NameB, 
    MAX(t.ValueA), 
    MAX(t.ValueB) 
FROM SampleView t 
GROUP BY t.Id 
ORDER BY t.Id 
+0

Il mio male, avrei dovuto dire che non volevo una query correlata. Tuttavia, dal momento che la tua risposta è corretta (+1) da me :) – Christos

0

Una possibile variante è quella di utilizzare ROW_NUMBER due volte:

WITH 
CTE_NameA 
AS 
(
    SELECT 
     Id, 
     NameA, 
     ROW_NUMBER() OVER (PARTITION BY ID ORDER BY LEN(NameA) DESC) AS rnA 
    FROM SampleView 
) 
,CTE_NameB 
AS 
(
    SELECT 
     Id, 
     NameB, 
     ROW_NUMBER() OVER (PARTITION BY ID ORDER BY LEN(NameB) DESC) AS rnB 
    FROM SampleView 
) 
SELECT 
    Id, 
    CTE_NameA.NameA, 
    CTE_NameB.NameB, 
    MAX(ValueA), 
    MAX(ValueB) 
FROM 
    SampleView 
    INNER JOIN CTE_NameA ON CTE_NameA.Id = SampleView.Id AND CTE_NameA.rnA = 1 
    INNER JOIN CTE_NameB ON CTE_NameB.Id = SampleView.Id AND CTE_NameB.rnB = 1 
GROUP BY Id 
ORDER BY Id; 
+1

Questo sembra molto: S – sagi