Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.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
在oracle sql中联接2个表_Sql_Oracle_Join - Fatal编程技术网

在oracle sql中联接2个表

在oracle sql中联接2个表,sql,oracle,join,Sql,Oracle,Join,以下是我开始使用的配置: DROP TABLE ruleset1; CREATE TABLE ruleset1 (id int not null unique,score_rule1 float default 0.0,score_rule2 float default 0.0,score_rule3 float default 0.0); DROP TABLE ruleset2; CREATE TABLE ruleset2 (id int not null unique,score

以下是我开始使用的配置:

DROP TABLE  ruleset1;
CREATE TABLE  ruleset1  (id int not null unique,score_rule1 float default 0.0,score_rule2 float default 0.0,score_rule3 float default 0.0);
DROP TABLE  ruleset2;
CREATE TABLE  ruleset2  (id int not null unique,score_rule1 float default 0.0,score_rule2 float default 0.0,score_rule3 float default 0.0);

insert into ruleset1 (id, score_rule1, score_rule2, score_rule3) values (0,0.8,0,0);
insert into ruleset1 (id, score_rule1, score_rule2, score_rule3) values (1,0,0.1,0);
insert into ruleset2 (id, score_rule1, score_rule2, score_rule3) values (0,0,0,0.3);
insert into ruleset2 (id, score_rule1, score_rule2, score_rule3) values (2,0,0.2,0);
我现在有两张桌子 规则集1:

| ID | SCORE_RULE1 | SCORE_RULE2 | SCORE_RULE3 
================================================
| 0  |    0.8      |     0       |     0     
| 1  |    0        |     0.1     |     0
和规则集2:

| ID | SCORE_RULE1 | SCORE_RULE2 | SCORE_RULE3 
================================================
| 0  |    0        |     0       |     0.3     
| 2  |    0        |     0.2     |     0
我想把它们连接起来,计算非零列的平均值,如下所示:

| ID | Average  
================
| 0  |    0.55 
| 1  |    0.1 
| 2  |    0.2 
我目前的查询是:

select * from ruleset1 full outer join ruleset2 on ruleset1.id = ruleset2.id;
这给了一个丑陋的结果:

| ID | SCORE_RULE1 | SCORE_RULE2 | SCORE_RULE3 | ID | SCORE_RULE1 | SCORE_RULE2 | SCORE_RULE3
============================================================================================
| 0  |     .8      |       0     |      0      | 0  |      0      |      0      |   .3
| -  |     -       |       -     |      -      | 2  |      0      |      .2     |   0
| 1  |     0       |       .1    |      0      | -  |      -      |      -      |   -
有谁能帮我提出一个更好的问题吗? 多谢各位

当然,avg不会忽略零,只忽略空值,因此可以使用NULLIFcolumn,0

但是,当您获得非规范化数据时,您只需动态地对其进行规范化:

select id, avg(score)
from
 (
    select id, score_rule1   score 
        from ruleset1 where score_rule1 <> 0
    union all 
    select id, score_rule2 from ruleset1 where score_rule2 <> 0
    union all
    select id, score_rule3 from ruleset1 where score_rule3 <> 0
    union all 
    select id, score_rule1 from ruleset2 where score_rule1 <> 0
    union all 
    select id, score_rule2 from ruleset2 where score_rule2 <> 0
    union all 
    select id, score_rule3 from ruleset2 where score_rule3 <> 0
 ) dt
group by id;

这假设核心规则列中没有空值。

这里有一个PostgreSQL示例,您可以使用Oracle进行调整。对不起,SQLFiddle的Oracle不配合。由于Juan Carlos Oropeza的建议,以下代码在Oracle上运行良好:

SELECT s.id, AVG(s.score)
FROM(
SELECT id,score_rule1+score_rule2+score_rule3 as score
FROM ruleset2
UNION ALL
SELECT id,(score_rule1+score_rule2+score_rule3) as score
FROM ruleset1) s

group by s.id
SQLFiddle with PostgreSQL版本在此处:

此示例使用union组合来自两个表的id。这样做允许ruleset1和ruleset2中的相同ID在结果中只出现一次。r是这个生成的表的别名


然后将所有ID与两个表保持连接。在求和过程中,左联接产生的空值可能会影响结果。因此,在数学中,空值合并为零

dnoeth是一个简单明了的答案

在这里,我只是在玩COALESCE和NVL2

然后,您的平均值为sum/tot

将所有两个表合并,取消PIVOT,使用nullif将零更改为null,并使用标准平均值聚合函数:

select id, avg(nullif(value, 0)) as avg_value from (
  select * from ruleset1
  union all
  select * from ruleset2
)
unpivot ( value for column_name in (score_rule1, score_rule2, score_rule3))
group by id
order by id
;

        ID  AVG_VALUE
---------- ----------
         0        .55
         1         .1
         2         .2

那么,你不需要在某个地方使用avg函数吗?你的桌子设计看起来有缺陷。为什么您需要两张存储相同内容的桌子?在一个表中添加一个规则集列。在计算平均值时,你是否忽略了零?是的,我只是忽略了零,而对于avg函数,它似乎不起作用。你可以解释你是如何得到0.55-0.1-0.2的,你知道,对于我们这些从大学开始就不太喜欢统计的人来说:我不明白,为什么忽略0值?这不是平均值,是吗?很接近,但op需要非零值的平均值。需要解释你的答案是什么。仅仅发布代码并不一定有帮助。谢谢你的回答。我想问你,这在执行时间上是否很重要?还是有更快的方法?@msalem看起来效率很高。但您可以试试看,解释计划可能需要为两个表上的每个分数规则包含索引。@M问题:我添加了第二个查询,以便每个表只选择一次,如果这样更有效,只需检查实际资源使用情况。如果要删除union,我的版本只有一个联接,但是你还是应该用测试看看哪个版本最快。@JuanCarlosOropeza:太多的联合,我更喜欢联合而不是完全的外部联合-试着也有mysql,postgres和MSSqlSweet!谢谢你,@JuanCarlosOropeza。我不知道雷克斯特的存在。非常感谢。我仍然使用SQLFIDLE,因为它有文本到DDL的功能。然后将DDL移动到rexter。顺便说一句,检查你的网站,请下定决心,3个理由从git移动到svn,3个理由从svn移动到git。这个查询似乎非常有效,但是如果其中一个表没有3列score_rule1、score_rule2、score_rule3怎么办?@msalem-我只能回答你问的问题。我怎么知道你在现实生活中的例子还有什么?如果其中一个表没有这3列,你是什么意思?它有什么,只有一个ID为的列?
select
  r.id,
  sum(coalesce(r1.score_rule1,0) + 
      coalesce(r1.score_rule2,0) + 
      coalesce(r1.score_rule3,0) +
      coalesce(r2.score_rule1,0) + 
      coalesce(r2.score_rule2,0) + 
      coalesce(r2.score_rule3,0)
      )
      /
  sum(case when coalesce(r1.score_rule1,0) <> 0 then 1 else 0 end +
      case when coalesce(r1.score_rule2,0) <> 0 then 1 else 0 end +
      case when coalesce(r1.score_rule3,0) <> 0 then 1 else 0 end +
      case when coalesce(r2.score_rule1,0) <> 0 then 1 else 0 end +
      case when coalesce(r2.score_rule2,0) <> 0 then 1 else 0 end +
      case when coalesce(r2.score_rule3,0) <> 0 then 1 else 0 end) as Average

from

  (select id from ruleset1
  union
  select id from ruleset2) r

left join ruleset1 r1 on r.id = r1.id
left join ruleset2 r2 on r.id = r2.id

group by r.id
select COALESCE(r.ID, s.ID),
  COALESCE(r.score_rule1, 0) + 
  COALESCE(r.score_rule2, 0) + 
  COALESCE(r.score_rule3, 0) +
  COALESCE(s.score_rule1, 0) + 
  COALESCE(s.score_rule2, 0) + 
  COALESCE(s.score_rule3, 0) as sum,

  NVL2(r.score_rule1, 0, 1) + 
  NVL2(r.score_rule2, 0, 1) + 
  NVL2(r.score_rule3, 0, 1) + 
  NVL2(s.score_rule1, 0, 1) + 
  NVL2(s.score_rule2, 0, 1) + 
  NVL2(s.score_rule3, 0, 1) as tot

from ruleset1 r
full outer join ruleset2 s
  on ruleset1.id = ruleset2.id;
select id, avg(nullif(value, 0)) as avg_value from (
  select * from ruleset1
  union all
  select * from ruleset2
)
unpivot ( value for column_name in (score_rule1, score_rule2, score_rule3))
group by id
order by id
;

        ID  AVG_VALUE
---------- ----------
         0        .55
         1         .1
         2         .2