Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何确定实体在多个数据库记录中是否一直处于活动状态?_Sql_Oracle - Fatal编程技术网

Sql 如何确定实体在多个数据库记录中是否一直处于活动状态?

Sql 如何确定实体在多个数据库记录中是否一直处于活动状态?,sql,oracle,Sql,Oracle,示例数据集,其中每行记录一个独特的个人/专业组合的一段时间的有效时间段 注意:本示例数据集中显示了属于以下每个person_ID的所有记录 注2:终止日期9999/12/31仅表示此人目前正在该专业注册 最终目标数据集,其中有一个新的列,指示每个人是否在2017年全年连续注册专业 TBL_MAJORS_2 Person_ID Major Effective_Date Termination_Date Active_Throughout_2017 76

示例数据集,其中每行记录一个独特的个人/专业组合的一段时间的有效时间段

注意:本示例数据集中显示了属于以下每个person_ID的所有记录

注2:终止日期9999/12/31仅表示此人目前正在该专业注册

最终目标数据集,其中有一个新的列,指示每个人是否在2017年全年连续注册专业

TBL_MAJORS_2

Person_ID   Major         Effective_Date   Termination_Date   Active_Throughout_2017
76          Biology       2016/8/1         2017/2/24          1
76          Accounting    2017/2/25        2017/4/15          1
76          Math          2017/4/16        9999/12/31         1
102         Physics       2016/8/1         2018/7/21          1
58          Literature    2016/8/1         2017/5/13          0
94          Art History   2016/8/1         2017/8/30          0
94          Comp Sci      2018/3/1         9999/12/31         0
再解释一下

例如,76人有三个不同的专业,从2016年8月1日持续到9999年12月31日(即他们目前正在注册),因此他们在2017年持续注册

另一方面,94人有两个不同的专业,但从2017年8月31日到2018年2月28日,他们的活动存在差距,因此他们在2017年没有连续注册


有人能帮我做到这一点吗?如果你能让它表现得很好,你会得到额外的荣誉。。。我想这可能会涉及某种窗口/分析功能,但我真的被难倒了。

可以这样做:

WITH tbl_majors AS (SELECT 76 person_id, 'Biology' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('24/02/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 76 person_id, 'Accounting' major, to_date('25/02/2017', 'dd/mm/yyyy') effective_date, to_date('15/04/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 76 person_id, 'Math' major, to_date('16/04/2017', 'dd/mm/yyyy') effective_date, to_date('31/12/9999', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 102 person_id, 'Physics' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('21/07/2018', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 58 person_id, 'Literature' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('13/05/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 94 person_id, 'Art History' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('30/08/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 94 person_id, 'Comp Sci' major, to_date('01/03/2018', 'dd/mm/yyyy') effective_date, to_date('31/12/9999', 'dd/mm/yyyy') termination_date FROM dual)
SELECT person_id,
       major,
       effective_date,
       termination_date,
       CASE WHEN to_date('01/01/2017', 'dd/mm/yyyy') >= MIN(effective_date) OVER (PARTITION BY person_id, grp)
                 AND to_date('31/12/2017', 'dd/mm/yyyy') <= MAX(termination_date) OVER (PARTITION BY person_id, grp)
                 THEN 1
            ELSE 0
       END active_throughout_2017
FROM   (SELECT person_id,
               major,
               effective_date,
               termination_date,
               SUM(new_grp_start) OVER (PARTITION BY person_id ORDER BY effective_date) grp
        FROM   (SELECT person_id,
                       major,
                       effective_date,
                       termination_date,
                       CASE WHEN effective_date = LAG(termination_date) OVER (PARTITION BY person_id ORDER BY effective_date) + 1 THEN 0 ELSE 1 END new_grp_start
                FROM   tbl_majors));

 PERSON_ID MAJOR       EFFECTIVE_DATE TERMINATION_DATE ACTIVE_THROUGHOUT_2017
---------- ----------- -------------- ---------------- ----------------------
        58 Literature  01/08/2016     13/05/2017                            0
        76 Accounting  25/02/2017     15/04/2017                            1
        76 Biology     01/08/2016     24/02/2017                            1
        76 Math        16/04/2017     31/12/9999                            1
        94 Art History 01/08/2016     30/08/2017                            0
        94 Comp Sci    01/03/2018     31/12/9999                            0
       102 Physics     01/08/2016     21/07/2018                            1
正如您所看到的,它比我原来的解决方案优雅得多。您应该测试这两种方法,看看哪一种对您的数据更有效,等等


两种解决方案都假设不会有重叠(即,学生在任何时候都只会有一个专业);您必须相应地调整它们,以适应某个人一次可能拥有多个专业的情况。

可以这样做:

WITH tbl_majors AS (SELECT 76 person_id, 'Biology' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('24/02/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 76 person_id, 'Accounting' major, to_date('25/02/2017', 'dd/mm/yyyy') effective_date, to_date('15/04/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 76 person_id, 'Math' major, to_date('16/04/2017', 'dd/mm/yyyy') effective_date, to_date('31/12/9999', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 102 person_id, 'Physics' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('21/07/2018', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 58 person_id, 'Literature' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('13/05/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 94 person_id, 'Art History' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('30/08/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 94 person_id, 'Comp Sci' major, to_date('01/03/2018', 'dd/mm/yyyy') effective_date, to_date('31/12/9999', 'dd/mm/yyyy') termination_date FROM dual)
SELECT person_id,
       major,
       effective_date,
       termination_date,
       CASE WHEN to_date('01/01/2017', 'dd/mm/yyyy') >= MIN(effective_date) OVER (PARTITION BY person_id, grp)
                 AND to_date('31/12/2017', 'dd/mm/yyyy') <= MAX(termination_date) OVER (PARTITION BY person_id, grp)
                 THEN 1
            ELSE 0
       END active_throughout_2017
FROM   (SELECT person_id,
               major,
               effective_date,
               termination_date,
               SUM(new_grp_start) OVER (PARTITION BY person_id ORDER BY effective_date) grp
        FROM   (SELECT person_id,
                       major,
                       effective_date,
                       termination_date,
                       CASE WHEN effective_date = LAG(termination_date) OVER (PARTITION BY person_id ORDER BY effective_date) + 1 THEN 0 ELSE 1 END new_grp_start
                FROM   tbl_majors));

 PERSON_ID MAJOR       EFFECTIVE_DATE TERMINATION_DATE ACTIVE_THROUGHOUT_2017
---------- ----------- -------------- ---------------- ----------------------
        58 Literature  01/08/2016     13/05/2017                            0
        76 Accounting  25/02/2017     15/04/2017                            1
        76 Biology     01/08/2016     24/02/2017                            1
        76 Math        16/04/2017     31/12/9999                            1
        94 Art History 01/08/2016     30/08/2017                            0
        94 Comp Sci    01/03/2018     31/12/9999                            0
       102 Physics     01/08/2016     21/07/2018                            1
正如您所看到的,它比我原来的解决方案优雅得多。您应该测试这两种方法,看看哪一种对您的数据更有效,等等


两种解决方案都假设不会有重叠(即,学生在任何时候都只会有一个专业);您必须相应地调整它们,以适应可能有人同时拥有多个专业的情况。

好吧,我可以给您一个提示-对于每个记录,计算2017年内每个人注册的天数。然后将其汇总并加入原始表,检查2017年登记的总天数是否等于2017年的总天数。哦,这太好了,应该可以与我的实际数据集很好地配合。谢谢你提出了这个有用的想法。也许你的答案就在这里:好吧,我可以给你一个提示——对于每个记录,计算2017年内每个人注册的天数。然后将其汇总并加入原始表,检查2017年登记的总天数是否等于2017年的总天数。哦,这太好了,应该可以与我的实际数据集很好地配合。谢谢你的建议。也许你的答案就在这里:非常感谢。你是我这一天的英雄。不过,我要说的是,GSazheniuk总结2017年的想法比我的答案更优雅、更简单,也更有可能更有效!非常感谢你。你是我这一天的英雄。不过,我要说的是,GSazheniuk总结2017年的想法比我的答案更优雅、更简单,也更有可能更有效!
WITH tbl_majors AS (SELECT 76 person_id, 'Biology' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('24/02/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 76 person_id, 'Accounting' major, to_date('25/02/2017', 'dd/mm/yyyy') effective_date, to_date('15/04/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 76 person_id, 'Math' major, to_date('16/04/2017', 'dd/mm/yyyy') effective_date, to_date('31/12/9999', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 102 person_id, 'Physics' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('21/07/2018', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 58 person_id, 'Literature' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('13/05/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 94 person_id, 'Art History' major, to_date('01/08/2016', 'dd/mm/yyyy') effective_date, to_date('30/08/2017', 'dd/mm/yyyy') termination_date FROM dual UNION ALL
                    SELECT 94 person_id, 'Comp Sci' major, to_date('01/03/2018', 'dd/mm/yyyy') effective_date, to_date('31/12/9999', 'dd/mm/yyyy') termination_date FROM dual)
SELECT person_id,
       major,
       effective_date,
       termination_date,
       CASE WHEN SUM(LEAST(to_date('31/12/2017', 'dd/mm/yyyy'), termination_date) + 1 - GREATEST(to_date('01/01/2017', 'dd/mm/yyyy'), effective_date)) OVER (PARTITION BY person_id)
                   = to_date('31/12/2017', 'dd/mm/yyyy') + 1 - to_date('01/01/2017', 'dd/mm/yyyy')
                 THEN 1
            ELSE 0
       END active_throughout_2017
FROM   tbl_majors;