2016-03-16 15 views
5

Mam widok sql, nazwijmy go SampleView, którego wyniki mają następujący format.Grupa tsql pobiera wartość kolumny alfanumerycznej o maksymalnej długości

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

Zestaw wyników widoku zawiera wiersze, które mogą mieć ten sam Id lub nie. Gdy istnieją dwie lub więcej wierszy z tym samym identyfikatorem, chciałbym dostać coś następnego

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

Odnośnie kolumn Id, ValueA i ValueB nie ma żadnego problemu. Z drugiej strony używanie MAX zarówno dla NameA i NameB rzeczy nie są zgodne z oczekiwaniami. Po przeszukaniu i przeszukaniu zdałem sobie sprawę, że MAX nie ma "oczekiwanego" zachowania dla kolumn alfanumerycznych. Mówiąc o spodziewanym, mam na myśli użycie MAX w moim przypadku, byłoby zwrócić wartość NameA z maksymalną liczbą znaków, MAX(LEN(NameA)). Muszę tu wspomnieć, że nie ma żadnej możliwości, aby NameA miał dwie wartości dla tego samego Id o tej samej długości. To może sprawić, że problem będzie łatwiejszy do rozwiązania.

Używam SQL Server 2012 i TSQL.

Czy masz jakieś sugestie, w jaki sposób mogę poradzić sobie z tym problemem?

Z góry dziękuję bardzo za pomoc.

Odpowiedz

2

Można użyć funkcji okna:

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

Dziękuję bardzo! To, że chcę :) – Christos

2

Można użyć skorelowanych kwerendy tak:

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

Moje złe, powinienem był wspomnieć, że nie chcę, aby było to skorelowane zapytanie. Jednakże, ponieważ twoja odpowiedź jest poprawna (+1) ode mnie :) – Christos

0

Możliwym wariantem jest użycie ROW_NUMBER dwukrotnie:

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

To wydaje się być bardzo: S – sagi

Powiązane problemy