Il più grande valore di MySQL in fila?

Sto usando MySQL con PHP. Questo è come il mio tavolo: (Sto usando 3 valori, ma ce ne sono altri)

  id |  1 |  2 |  3
 --- + --- + --- + ----
 1 |  3 | 12 | -29
 2 |  5 | 8 | 8
 3 |  99 | 7 | NULL

Ho bisogno di get il nome della colonna del valore più grande in una determinata row. Dovrebbe get:

  id |  maxcol
 --- + -------
 1 |  2
 2 |  2
 3 |  1 

Ci sono domande che lo faranno? Ci sto provando, ma non riesco a farlo funzionare correttamente.

Stai cercando qualcosa come la function GREATEST ? Per esempio:

 SELECT id, GREATEST(col1, col2, col3) FROM tbl WHERE ... 

Combinalo con un'istruzione CASE per get i nomi delle colonne:

 SELECT id, CASE GREATEST(COALESCE(`1`, -2147483646), COALESCE(`2`, -2147483646), COALESCE(`3`, -2147483646)) WHEN `1` THEN 1 WHEN `2` THEN 2 WHEN `3` THEN 3 ELSE 0 END AS maxcol FROM tbl WHERE ... 

Non è carino Faresti meglio a seguire il suggerimento di Bill Karwin e normalizzarlo, o semplicemente prenderti cura di ciò in PHP.

 function findcol($cmp, $arr, $cols=Null) { if (is_null($cols)) { $cols = arrays_keys($arr); } $name = arrays_shift($cols); foreach ($cols as $col) { if (call_user_func($cmp, $arr[$name], $arr[$col])) { $name = $col; } } return $name; } function maxcol($arr, $cols=Null) { return findcol(create_function('$a, $b', 'return $a < $b;'), $arr, $cols); } 

Questo è un ottimo esempio del modo in cui la normalizzazione aiuta a semplificare la progettazione delle query. In First Normal Form , dovresti creare un'altra tabella in modo che tutti i valori si trovino in una colonna, su righe separate.

Poiché hai utilizzato gruppi ripetuti per archiviare i tuoi valori su tre colonne, puoi trovare la colonna con il valore maggiore in questo modo:

 SELECT id, IF(col1>col2 AND col1>col3, 'col1', IF(col2>col3, 'col2', 'col3')) AS column_with_greatest_value FROM mytable; 

La risposta breve è che non esiste un mezzo semplice per farlo tramite una query. Dovresti trasporre i tuoi dati e quindi determinare il valore più grande in questo modo. Quindi qualcosa come:

 Select Id, ColumnName, Value From ( Select '1' As ColumnName, Id, [1] As Value From Table Union All Select '2', Id, [2] From Table Union All Select '3', Id, [3] From Table ) As Z Where Exists( Select 1 From ( Select '1' As ColumnName, Id, [1] As Value From Table Union All Select '2', Id, [2] From Table Union All Select '3', Id, [3] From Table ) As Z2 Where Z2.Id = Z.Id Group By Z2.Id Having Max(Z2.Value) = Z.Value ) Order By Id 

Questa soluzione dipende da un set fisso di colonne in cui fondamentalmente le colonne vengono denominate nelle query UNION ALL. Inoltre, se hai due colonne con valori identici per lo stesso Id, otterrai delle righe duplicate.

Questa query restituirà il valore massimo indipendentemente dai valori NULL

 SELECT MAX(value) FROM (SELECT 1 column_no, col1 value FROM anotherunamedtable UNION ALL SELECT 2, col2 FROM anotherunamedtable UNION ALL SELECT 3, col3 FROM anotherunamedtable) t 

Se hai davvero bisogno del numero di colonna, allora

 SELECT id, (SELECT column_no FROM (SELECT 1 column_no, col1 value FROM anotherunamedtable WHERE id = t.id UNION ALL SELECT 2, col2 FROM anotherunamedtable WHERE id = t.id UNION ALL SELECT 3, col3 FROM anotherunamedtable WHERE id = t.id) s ORDER BY max_value DESC LIMIT 1)) as column_no FROM anotherunamedtable t 

Ma penso che l'ultima query potrebbe rivelarsi eccezionalmente orribile. (Le query non sono state testate)

Nel lato php, potresti fare qualcosa del genere:

 foreach ($rows as $key => $row) { $bestCol = $best = -99999; foreach ($row as $col => $value) { if ($col == 'id') continue; // skip ID column if ($value > $best) { $bestcol = $col; $best = $value; } } $rows[$key]['best'] = $bestCol; } 

O qualcosa di simile …

Foreste e alberi, ecco una soluzione banale e veloce (a patto che non abbia fumble); l'espressione cerca semplicemente la colonna più grande nella row

 SELECT id, CASE COALESCE(col1, -2147483648) >= COALESCE(col2, -2147483648) WHEN CASE COALESCE(col2, -2147483648) >= COALESCE(col3, -2147483648) WHEN true THEN 1 ELSE CASE COALESCE(col1, -2147483648) >= COALESCE(col3, -2147483648) WHEN true THEN 1 ELSE 3 END END ELSE CASE COALESCE(col2, -2147483648) >= COALESCE(col3, -2147483648) WHEN true 2 ELSE 3 END END FROM table t 

una versione con IF () potrebbe essere più leggibile, ma quanto sopra dovrebbe funzionare un po 'meglio Per trattare con NULLS è stato assunto un valore INT con un minimo di -2147483648, l'espressione potrebbe essere riscritta per trattare esplicitamente con valori nulli ma dovrebbe essere derivata in 8 casi diversi e viene lasciato come esercizio per l'OP.