SQL根据值优先的列取结果

SQL to fetch the result on the basis of the column value with value having the priorities

我正在尝试编写 SQL 以获得以下结果:

规则:


  1. 获取所有 PlanType 为 STO 的 taskId。
  2. 获取所有具有 PlanType AS MTO 的 taskId,这些 taskId 不存在于 PlanType AS STO 中。
  3. 获取所有带有 PlanType AS LTO 的 taskId,这些 taskId 不存在于 PlanType AS MTO 中。

下面是DDL/import SQL:

CREATE TABLE FTASK (
    id INT PRIMARY KEY,
    taskId VARCHAR2 (100) NOT NULL,
    PLANTYPE VARCHAR2 (100) 
);


INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (1,'T1','STO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (2,'T2','STO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (3,'T3','STO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (4,'T4','MTO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (5,'T5','MTO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (6,'T2','LTO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (7,'T1','LTO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (8,'T5','LTO');
INSERT INTO FTASK (ID,TASKID,PLANTYPE) VALUES (9,'T3','MTO');

期待以下结果:

我尝试使用 UNION 和 INTERSECT。 提前致谢。

一种方法使用 row_number()。您的类型按字母顺序排列,因此可以使用该事实:

select t.*
from (select t.*,
             row_number() over (partition by taskid order by plantype desc) as seqnum
      from ftask t
     ) t
where seqnum = 1;

如果在实际问题中类型不是字母顺序的,您可以修改 order by 以使用 case 表达式。但是,上面可以使用 (taskid, plantype desc).

上的索引

以上允许您获取所有列。如果你只有这三列,你也可以很容易地使用聚合:

select max(id) keep (dense_rank first order by plantype desc) as id,
      taskid,
      max(plantype) as plantype
from ftask
group by taskid;

keep 语法是 Oracle 实现“第一个”聚合函数的(相当冗长的)方式。

Here 是一个 db<>fiddle.

您可以使用 Gordon 的答案,或者您也可以使用具有适当 CASE 表达式的行号

WITH cte AS (
    SELECT f.*, ROW_NUMBER() OVER (PARTITION BY TASKID
                                   ORDER BY CASE PLANTYPE WHEN 'LTO' THEN 1
                                                          WHEN 'MTO' THEN 2
                                                          WHEN 'STO' THEN 3 END DESC) rn
    FROM FTASK f
)

SELECT ID, TASKID, PLANTYPE
FROM cte
WHERE rn = 1;

试试这个。我认为它非常适合你。
从在线尝试:http://sqlfiddle.com/#!4/7b597/1

  SELECT id, TASKID, PLANTYPE
    FROM (SELECT id,
                 TASKID,
                 PLANTYPE,
                 CASE
                    WHEN PLANTYPE = 'STO' THEN 1
                    WHEN PLANTYPE = 'MTO' THEN 2
                    WHEN PLANTYPE = 'LTO' THEN 3
                 END
                    order_by
            FROM (SELECT id, TASKID, PLANTYPE
                    FROM FTASK
                   WHERE PLANTYPE = 'STO'
                  UNION ALL
                  SELECT id, TASKID, PLANTYPE
                    FROM FTASK
                   WHERE     PLANTYPE = 'MTO'
                         AND TASKID NOT IN (SELECT TASKID
                                              FROM FTASK
                                             WHERE PLANTYPE = 'STO')
                  UNION ALL
                  SELECT id, TASKID, PLANTYPE
                    FROM FTASK
                   WHERE     PLANTYPE = 'LTO'
                         AND TASKID NOT IN (SELECT TASKID
                                              FROM FTASK
                                             WHERE PLANTYPE = 'MTO')))
ORDER BY order_by, TASKID;