如何获取最小函数结果的列名?

时间:2014-12-19 13:58:54

标签: mysql sql postgresql

我有一个员工表,如下所示:

| id | name | q1 | q2 | q3 | q4 |
+----+------+----+----+----+----+
| 1  | John | 20 | 30 | 10 | 4  |
| 2  | Ram  | 07 | 10 | 03 | 4  |
| 3  | John | 05 | 03 | 15 | 40 |
| 4  | Sree | 12 | 05 | 20 | 25 |

我需要获得id等于4的问题的最小值和最大值。在这种情况下,我需要返回5和25。我使用以下查询实现了这一点:

SELECT id, name,
  LEAST(q1, q2, q3, q4) AS minValue,
  GREATEST(q1, q2, q3, q4) AS maxValue
FROM employee
WHERE id = 4;

但是这不会返回的是问题ID。如何调整查询以显示q2是最小值,q4是最大值?我知道我可以写一个大案例陈述,但我也觉得可以用连接来完成,但我无法理解。

注意:这是针对postgresql数据库的,但我也标记了MySQL,因为我知道它也支持LEASTGREATEST函数。如果两者的解决方案非常不同,那么我将删除此注释并提出单独的问题。

修改

我已经有SQL Fiddle

4 个答案:

答案 0 :(得分:3)

您可以使用case声明:

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

(注意:它将丢失关于关系的信息。)

如果你对关系感兴趣,用子查询和数组来接近它就可以了:

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;

答案 1 :(得分:2)

我会使用CASE语句比较每列的最大值,直到找到匹配为止

不完美,因为它不会很快,并且当多个共享相同的最大值时也会找到第一列: -

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;

编辑 - 使用联接,我怀疑这会更糟糕: -

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;

答案 2 :(得分:1)

下面将显示最大值和最小值。它还将显示共享的最大值和最小值。 如果max和min值恰好相同,它将会下降。 (例如,所有值都相同)

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

答案 3 :(得分:0)

使用"simple" or "switched" CASE声明:

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

如果是关系,将报告列表中的第一项。