How to get the column name of the result of a least function?

后端 未结 4 994
北海茫月
北海茫月 2021-01-27 03:24

I have an employee table that looks like this:

| id | name | q1 | q2 | q3 | q4 |
+----+------+----+----+----+----+
| 1  | John | 20 | 30 | 10 | 4  |
| 2  | Ram           


        
相关标签:
4条回答
  • 2021-01-27 04:02

    I would use a CASE statement to compare the greatest value against each column until a match is found

    Not perfect as it won't be fast and will also just find the first column when more than one share the same max value:-

    SELECT id, 
        name,
        LEAST(q1, q2, q3, q4) AS minValue,
        CASE LEAST(q1, q2, q3, q4)
            WHEN q1 THEN 'q1'
            WHEN q2 THEN 'q2'
            WHEN q3 THEN 'q3'
            ELSE 'q4'
        END,
        GREATEST(q1, q2, q3, q4) AS maxValue,
        CASE GREATEST(q1, q2, q3, q4)
            WHEN q1 THEN 'q1'
            WHEN q2 THEN 'q2'
            WHEN q3 THEN 'q3'
            ELSE 'q4'
        END
    FROM employee
    WHERE id = 4;
    

    EDIT - using a join, and I suspect this will be far worse:-

    SELECT a0.id, 
        a0.name,
        LEAST(a0.q1, a0.q2, a0.q3, a0.q4) AS minValue,
        CASE 
            WHEN a1.id IS NULL THEN 'q1'
            WHEN a2.id IS NULL THEN 'q2'
            WHEN a3.id IS NULL THEN 'q3'
            ELSE 'q4'
        END,
        GREATEST(a0.q1, a0.q2, a0.q3, a0.q4) AS maxValue,
        CASE GREATEST(q1, q2, q3, q4)
            WHEN a15.id IS NULL THEN 'q1'
            WHEN a16.id IS NULL THEN 'q2'
            WHEN a17.id IS NULL THEN 'q3'
            ELSE 'q4'
        END
    FROM employee a0
    LEFT OUTER JOIN employee a1 ON a0.id = a1.id AND LEAST(a0.q1, a0.q2, a0.q3, a0.q4) = a1.q1 
    LEFT OUTER JOIN employee a2 ON a0.id = a2.id AND LEAST(a0.q1, a0.q2, a0.q3, a0.q4) = a2.q2 
    LEFT OUTER JOIN employee a3 ON a0.id = a3.id AND LEAST(a0.q1, a0.q2, a0.q3, a0.q4) = a3.q3 
    LEFT OUTER JOIN employee a4 ON a0.id = a4.id AND LEAST(a0.q1, a0.q2, a0.q3, a0.q4) = a4.q4 
    LEFT OUTER JOIN employee a11 ON a0.id = a11.id AND GREATEST(a0.q1, a0.q2, a0.q3, a0.q4) = a1.q11 
    LEFT OUTER JOIN employee a12 ON a0.id = a12.id AND GREATEST(a0.q1, a0.q2, a0.q3, a0.q4) = a2.q12 
    LEFT OUTER JOIN employee a13 ON a0.id = a13.id AND GREATEST(a0.q1, a0.q2, a0.q3, a0.q4) = a3.q13 
    LEFT OUTER JOIN employee a14 ON a0.id = a14.id AND GREATEST(a0.q1, a0.q2, a0.q3, a0.q4) = a4.q14 
    WHERE a0.id = 4;
    
    0 讨论(0)
  • 2021-01-27 04:04

    You can use a case statement:

    CASE
    WHEN LEAST(q1, q2, q3, q4) = q1 THEN 'q1'
    WHEN LEAST(q1, q2, q3, q4) = q2 THEN 'q2'
    WHEN LEAST(q1, q2, q3, q4) = q3 THEN 'q3'
    ELSE 'q4'
    END as minQuestion
    

    (Note: it will lose information over ties.)

    If you're interested in ties, approaching it with a subquery and arrays will do the trick:

    with employee as (
      select id, q1, q2, q3, q4
      from (values
        (1, 1, 1, 3, 4),
        (2, 4, 3, 1, 1)
      ) as rows (id, q1, q2, q3, q4)
    )
    
    SELECT least(q1, q2, q3, q4),
           array(
             select q
             from (values (q1, 'q1'),
                          (q2, 'q2'),
                          (q3, 'q3'),
                          (q4, 'q4')
                  ) as rows (v, q)
             where v = least(q1, q2, q3, q4)
           ) as minQuestions
    FROM employee e
    WHERE e.id = 1;
    
    0 讨论(0)
  • 2021-01-27 04:04

    Below will show max and min values. It will also show shared max and min values. It will fall down if max and min values happen to be the same. (eg all values are the same)

    SELECT
    employee.id, x.name,
    CASE 
    WHEN employee.q1 = x.minVal THEN 'minval' 
    WHEN employee.q1 = x.maxVal THEN 'maxval'
    ELSE ''
    END AS q1,
    CASE 
    WHEN employee.q2 = x.minVal THEN 'minval' 
    WHEN employee.q2 = x.maxVal THEN 'maxval' 
    ELSE '' END AS q2,
    CASE 
    WHEN employee.q3 = x.minVal THEN 'minval' 
    WHEN employee.q3 = x.maxVal THEN 'maxval' 
    ELSE '' END AS q3,
    CASE 
    WHEN employee.q4 = x.minVal THEN 'minval' 
    WHEN employee.q4 = x.maxVal THEN 'maxval' 
    ELSE '' END AS q4,
    x.minVal,
    x.maxVal
    FROM employee
    INNER JOIN
    (
    SELECT e.id, e.name,
      LEAST(e.q1, e.q2, e.q3, e.q4) AS minVal,
      GREATEST(e.q1, e.q2, e.q3, e.q4) AS maxVal
    FROM employee e
    WHERE e.id = 4
     ) x
    ON employee.id=x.id
    
    0 讨论(0)
  • 2021-01-27 04:17

    Use a "simple" or "switched" CASE statement:

    SELECT CASE LEAST(q1, q2, q3, q4)
              WHEN q1 THEN 'q1'
              WHEN q2 THEN 'q2'
              WHEN q3 THEN 'q3'
              ELSE 'q4'
           END as chosen_item
    

    In case of ties, the first item in the list will be reported.

    0 讨论(0)
提交回复
热议问题