Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.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_Database_Oracle_Querying - Fatal编程技术网

如何创建基于条件从多行获取数据的SQL查询?

如何创建基于条件从多行获取数据的SQL查询?,sql,database,oracle,querying,Sql,Database,Oracle,Querying,我有两张桌子: 保险信息表: Name |Insurance_ID|Insurance_Effective|Insurance_Expiry |Insurance_type John |30 |20100502 |20120502 |Primary Reggy |50 |20110904 |20160803 |Tertiary John

我有两张桌子:

保险信息表:

    Name   |Insurance_ID|Insurance_Effective|Insurance_Expiry   |Insurance_type
    John   |30          |20100502           |20120502           |Primary
    Reggy  |50          |20110904           |20160803           |Tertiary
    John   |54          |20120503           |20170403           |Primary
    Reggy  |30          |20120503           |20140101           |Secondary
    Reggy  |39          |20110904           |20160803           |Primary
服务表:

    Name  | Date_of_Service |Other_info
    John  | 20110102        |Foo
    John  | 20110102        |Bar
    Reggy | 20150304        |Sth
    John  | 20130206        |Other
现在我必须返回:

    Name  |Primary_Insurance | Secondary_Insurance | Tertiary_Insurance | Date_of_Service
    John  | 30               |null                 | null               |20110102
    John  | 54               |null                 | null               |20130206
    Reggy | 39               |null                 | 50                 |20150304
从服务表中每人每天最多只能有一个服务日期。此外,保险信息表中的一级、二级和三级保险被选中,其中保险生效日期<服务日期<人员服务的每个日期的保险到期日期


如何在Oracle SQL中编写此查询?

您似乎在寻找一个轴心点。在Oracle 11g之前,您可以使用
MAX
CASE
手动执行此操作:

select s.name,
  max(case when ii.insurance_type = 'Primary' then ii.insurance_id end)
    as primary_insurance,
  max(case when ii.insurance_type = 'Secondary' then ii.insurance_id end)
    as secondary_insurance,
  max(case when ii.insurance_type = 'Tertiary' then ii.insurance_id end)
     as tertiary_insurance,
  s.date_of_service
from service s
left join insurance_info ii on ii.name = s.name
  and s.date_of_service between ii.insurance_effective and ii.insurance_expiry
group by s.name, s.date_of_service
order by s.name, s.date_of_service;

NAME       PRIMARY_INSURANCE SECONDARY_INSURANCE TERTIARY_INSURANCE DATE_OF_SERVICE
---------- ----------------- ------------------- ------------------ ---------------
John                      30                                        02-JAN-11       
John                      54                                        06-FEB-13       
Reggy                     39                                     50 04-MAR-15       

这是建立在两个表之间的一个基本连接之上的,这两个表之间是相互关联的。三个
CASE
语句添加了伪列,其中包含。最后,
MAX
聚合将拆分出的值向下折叠,因此每个名称/服务日期只有一行


从11g开始,您可以使用内置的,并有效地为您做同样的事情:

select *
from (
  select s.name,
    s.date_of_service,
    ii.insurance_type,
    ii.insurance_id
  from service s
  left join insurance_info ii on ii.name = s.name
    and s.date_of_service between ii.insurance_effective and ii.insurance_expiry
)
pivot (max(insurance_id) as insurance for (insurance_type)
  in ('Primary' as primary, 'Secondary' as secondary, 'Tertiary' as tertiary))
order by name, date_of_service;

NAME       DATE_OF_SERVICE PRIMARY_INSURANCE SECONDARY_INSURANCE TERTIARY_INSURANCE
---------- --------------- ----------------- ------------------- ------------------
John       02-JAN-11                      30                                        
John       06-FEB-13                      54                                        
Reggy      04-MAR-15                      39                                     50 


我假设(希望)日期字段实际上是
DATE
而不是
VARCHAR2
值,如果需要,您只需将结果格式化为
YYYYMMDD
。如果它们是该格式的字符串,因为它们是可比较的,那么它仍然可以工作,但是您不应该将日期存储为字符串


另外,假设您希望日期范围包括在内,那么使用
BETWEEN
相当于
Insurance\u您尝试过什么吗?@TMNT2014这应该是一个答案,而不是一个注释。@TMNT2014为什么删除您的注释?我之前很忙,没有机会看一遍….+1,因为包含了SQL Fiddle。我不知道这件事=我仍然使用Oracle 10g:(你能解释一下MAX在这种情况下的用法吗?我对它的理解仅限于返回列中的最高值。@user3808188-它是这样做的,但是对于使用
case
生成的伪列中的最高值。我已经添加了一些解释;如果你查看额外的SQL Fiddle链接,希望它会更清晰。我不知道。)我看不出使用(CASE-WHEN(任何可能的选项)然后使用ID)和只使用ID之间的区别。据我所知,无论哪种方式,它都返回一个MAX函数正在运行的值。我看不出在这种情况下,我们是如何获得更少的具有完全匹配列的行的。即使在看到SQL Fiddle之后