2010-10-01 15 views
6

Mam kwerendę, która wygląda mniej więcej tak:wybierz nazwę kolumny z max zapytania

;WITH t as 
(
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1], 20 as [Col2], 20 as [Col3], 20 as [Col4] UNION ALL 
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1], 30 as [Col2], 40 as [Col3], 50 as [Col4] 
) 
SELECT RowNumber, ObjectID, 
     (
     SELECT MAX(Amount) 
     FROM (
       SELECT [Col1] AS Amount 
       UNION ALL 
       SELECT [Col2] 
       UNION ALL 
       SELECT [Col3] 
       UNION ALL 
       SELECT [Col4] 
       ) d 
     WHERE Amount > 0 
     ) 
FROM t 

Kwerenda działa prawidłowo, ale chcę wiedzieć, gdzie jest Max (Amount) pochodzi.

Tak więc w moim zestawie wyników, oprócz posiadania (RowNumber, ObjectId, Amount) chcę, aby nazwa kolumny (Col1, Col2, Col3, Col4) była łańcuchem.

Czy jest jakiś sposób to zrobić?

EDIT Pytanie z komentarzami: Jeżeli dwie kolumny mają taką samą max, może to być jeden? Tak, może to być jedna. Każda nazwa kolumny będzie działać tak długo, jak długo będę wiedział, skąd może pochodzić.

Korzystanie z SQL Server 2008

+0

Co RDBMS używasz? –

+1

Co jeśli zarówno Col1, jak i Col2 mają ten sam MAX: może to być jeden ...? – gbn

+0

Mam nadzieję, że nie przeszkadza mi, że właśnie zredagowałem kod, aby był to działający przykład, ponieważ nigdy wcześniej nie widziałem takiego podejścia. Zachęcamy do jego wycofania! –

Odpowiedz

1

Można użyć kombinacji UNPIVOT i OUTER APPLY:

;WITH t as  (
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1], 20 as [Col2], 
     20 as [Col3], 20 as [Col4] UNION ALL 
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1], 30 as [Col2], 
     40 as [Col3], 50 as [Col4]) 
SELECT 
    RowNumber, 
    ObjectID, 
    ColName, 
    ColAmount 
FROM t 
OUTER APPLY (
    SELECT TOP 1 
    ColName, 
    ColAmount 
    FROM 
    (
     SELECT 
     Col1, 
     Col2, 
     Col3, 
     Col4 
    ) x 
    UNPIVOT (
     ColAmount FOR ColName IN (Col1, Col2, Col3, Col4) 
    ) y 
    WHERE ColAmount > 0 
    ORDER BY ColAmount DESC 
) z 

wyniki:

RowNumber ObjectID ColName ColAmount 
----------- ----------- --------- ----------- 
1   1   Col2  20 
2   2   Col4  50 
+0

Dzięki, okazało się, że jest to najlepsze rozwiązanie tutaj. Nie wiedziałem o funkcji UNPIVOT, ale dokładnie tego szukałem. –

5

Nie MAX: Zastosowanie do góry, która unika łączną/GROUP BY.

Można również radzić sobie z duplikatów za pomocą opaskami

Nie jestem pewien, czy to, co mieliśmy było psuedo kodu lub sub-kwerendy, ale powinno to robić co chcesz

SELECT TOP 1 -- WITH TIES if needed 
    * 
FROM 
    (
    SELECT RowNumber, ObjectID, [Col1] AS Amount, 'Col1' AS ColName 
    FROM table 
    UNION ALL 
    SELECT RowNumber, ObjectID, [Col2], 'Col2' AS ColName 
    FROM table 
    UNION ALL 
    SELECT RowNumber, ObjectID, [Col3], 'Col3' AS ColName 
    FROM table 
    UNION ALL 
    SELECT RowNumber, ObjectID, [Col4], 'Col4' AS ColName 
    FROM table 
    ) foo 
WHERE Amount > 0 
ORDER BY Amount DESC 

Twoim głównym problemem jest to, że musisz dotknąć tabeli 4 razy, niezależnie od tego, jak to zrobisz, ponieważ podzapytanie zwraca tylko jedną wartość. Nie widzę również rozwiązania ROW_NUMBER (ale prawdopodobnie jest jeden ... :-)

+0

Jego zapytanie dotyczyło jednego wiersza. Nigdy nie wiedziałem, że możesz to zrobić. –

+0

@Martin Smith: Działa, ale nie wiem, jak uzyskać nazwę kolumny, ponieważ jest to podkwerenda, która pozwala tylko na jedną wartość. Zobacz następujące linki: http://sqlblogcasts.com/blogs/simons/archive/2006/05/08/Neat-trick-to-find-max-value-of-multiple-columns.aspx lub http: // sqlblogcasts. com/blogs/simons/archive/2006/05/16/Performance-of-MAX-trick.aspx – gbn

+0

Tak, nigdy wcześniej tego nie widziałem. Dzięki za linki! –

3

To jest niesprawdzone: jednak aby zobaczyć, co dzieje się z danymi, może to pomóc. Niezupełnie jakość kodu produkcyjnego:

SELECT RowNumber, ObjectID, 
     (
     SELECT MAX(Amount) 
     FROM (
       SELECT str([Col1]) + ", col1, " AS Amount 
       UNION ALL 
       SELECT str([Col2]) + ", col2" 
       UNION ALL 
       SELECT str([Col3]) + ", col3" 
       UNION ALL 
       SELECT str([Col4]) + ", col4" 
       ) 
     WHERE Amount > 0 
     ) 
FROM table 

str() jest funkcją "toString()" w Twoim systemie DBMS. Twój SQL wydaje się dość dziwny, z jakiego DBMS korzystasz?

+0

Musiałbyś mieć 'Kwota> '0'', ale to jest całkiem miłe + 1 – gbn

+0

To sprytny sposób robienia tego. Nie myślałem o dodawaniu nazwy kolumny jako takiego Stringa. Dzięki –

2

Dodawanie krok do user202553's answer

;WITH t1 as(
select 1 as RowNumber, 1 as ObjectID, 10 as [Col1], 20 as [Col2], 20 as [Col3], 20 as [Col4] UNION ALL 
select 2 as RowNumber, 2 as ObjectID, 20 as [Col1], 30 as [Col2], 40 as [Col3], 50000045 as [Col4] 
), 
t2 as(
SELECT RowNumber, ObjectID, 
     (
     SELECT TOP 1 CAST(C AS BINARY(4)) + CAST(Amount as BINARY(4)) 
     FROM (
       SELECT 'Col1' AS C, [Col1] AS Amount 
       UNION ALL 
       SELECT 'Col2' AS C, [Col2] 
       UNION ALL 
       SELECT 'Col3' AS C, [Col3] 
       UNION ALL 
       SELECT 'Col4' AS C, [Col4] 
       ) d 
     WHERE Amount > 0 
     ORDER BY Amount desc 
     ) AS Top1 
FROM t1 
) 
SELECT RowNumber, 
     ObjectID, 
     CAST(Left(Top1, 4) AS CHAR(4)) AS Col, 
     CAST(SUBSTRING(Top1,5,4) AS INT) AS Amount 
FROM t2 
+0

Dzięki, to jest całkiem czyste, a także –

+0

Nawet bardziej wtedy ciąg konkat: ustalona długość "kodowania" – gbn

Powiązane problemy