SQL Challenge - 显示具有特定列值的N(1,X或All)行

时间:2011-09-06 09:35:29

标签: mysql sql oracle postgresql

这是一个早上的挑战:你有一个像这样的行的表:

=> select * from candidates;
 id |   name   
----+----------
  1 | JOhn Doe
  2 | Melinda
  3 | Bill
  4 | Jane
(4 rows)

=> select * from evaluation order by id;
 id | score |                reason                
----+-------+--------------------------------------
  1 | RED   | Clueless!
  1 | AMBER | Came in dirty jeans
  2 | GREEN | Competenet and experienced
  2 | AMBER | Was chewing a gum
  3 | AMBER | No experience in the industry sector
  3 | AMBER | Has knowledge gaps
(6 rows)
约翰有一个红色,梅琳达有一个绿色和琥珀,比尔只有琥珀,而简尚未接受采访。

您的任务,如果您选择接受它,则生成一个显示Boss批准结果的查询。老板喜欢把结果表示为:

  • 如果候选人有绿色,则只显示绿色并忽略红色和琥珀色。
  • 如果候选人有红色和琥珀或只有琥珀然后显示所有这些,但是首先出现红色分数,这样如果RED非常糟糕,他可以跳过琥珀。
  • 为所有尚未接受采访的候选人('简')
  • 显示灰色

游戏规则:

  • 没有功能!必须是单个SQL查询(无论您需要多个子查询)
  • 接受任何SQL变体,但ANSI SQL 92或更高版本为您提供更多分数
  • 尽可能避免使用内联变量(MySQL中的@foo)

我自己的答案结果与小组思考一致:

SELECT *
FROM   evaluation e1
       NATURAL JOIN candidates
WHERE  score = 'GREEN'
        OR ( score IN ( 'RED', 'AMBER' )
             AND NOT EXISTS (SELECT 1
                             FROM   evaluation e2
                             WHERE  e1.id = e2.id
                                    AND score = 'GREEN') )
UNION
SELECT id,
       'GREY'              AS score,
       'Not yet evaluated' AS reason,
       name
FROM   candidates
WHERE  id NOT IN (SELECT id
                  FROM   evaluation)
ORDER  BY 1,
          2 DESC  

4 个答案:

答案 0 :(得分:4)

以下是过渡性SQL-92:

SELECT c.name, e.*
  FROM candidates AS c
       JOIN (
             SELECT *
               FROM evaluation
              WHERE score = 'GREEN'
             UNION
             SELECT *
               FROM evaluation AS e1
              WHERE score IN ('AMBER', 'RED')
                    AND NOT EXISTS (
                                    SELECT * 
                                      FROM evaluation AS e2
                                     WHERE e2.id = e1.id
                                           AND e2.score = 'GREEN'
                                   )                                    
            ) AS e 
          ON c.id = e.id
UNION
SELECT c.name, c.id, 'GREY', '(not interviewed)'
  FROM candidates AS c
 WHERE NOT EXISTS (
                   SELECT *
                     FROM evaluation AS e 
                    WHERE e.id = c.id
                   )
ORDER BY id, score DESC;

替代(中级SQL-92):

SELECT c.name, e.id, e.score, e.reason 
  FROM candidates AS c
       JOIN (
             SELECT *
               FROM evaluation
             EXCEPT
             SELECT *
               FROM evaluation
              WHERE score IN ('AMBER', 'RED')
                    AND id IN ( SELECT id FROM evaluation WHERE score = 'GREEN' )
            ) AS e 
          ON c.id = e.id
UNION
SELECT name, id, 'GREY' AS score, '(not interviewed)' AS reason
  FROM candidates
 WHERE id NOT IN ( SELECT id FROM evaluation )
ORDER BY id, score DESC;

答案 1 :(得分:3)

SELECT
        c.id                       AS id
      , c.name                     AS name
      , COALESCE(e.score, 'GREY')  AS score
      , e.reason                   AS reason
FROM 
        candidates    c
    LEFT JOIN
        evaluation    e
            ON e.id = c.id
WHERE
        e.score = 'GREEN'
    OR
        NOT EXISTS
          ( SELECT *
            FROM evaluation    ee
            WHERE ee.id = c.id
              AND ee.score = 'GREEN'
          )
ORDER BY
        id      ASC
      , score   DESC 

答案 2 :(得分:0)

           SELECT c.id,
               c.name,
               nvl(e.score, 'GREY'),
               nvl(e.reason, 'Not yet interviewed')
          FROM candidates c, evaluation e
         where c.id = e.id(+)
           and ((e.score = 'GREEN') or
               (e.score in ('RED', 'AMBER') and not exists
                (select null
                    from evaluation e2
                   where e2.id = e.id
                     and e2.score = 'GREEN')) or e.score is null)
         order by c.id, e.score desc;

答案 3 :(得分:0)

SELECT A.ID
    , A.NAME
    , B.SCORE
    , B.REASON
FROM CANDIDATES A
LEFT JOIN EVALUATION B
    ON A.ID = B.ID
WHERE B.SCORE = 'GREEN'
UNION
SELECT A.ID
    , A.NAME
    , COALESCE(B.SCORE,'GREY')
    , B.REASON
FROM CANDIDATES A
LEFT JOIN EVALUATION B
    ON A.ID = B.ID
WHERE A.ID NOT IN (SELECT ID FROM EVALUATION WHERE SCORE = 'GREEN')
ORDER BY ID, SCORE DESC;