如何将常见列(A,B)和(A,C)的2个查询转换为一个(A,B,C)?

时间:2010-11-24 09:28:05

标签: sql database oracle join

我目前有2个返回

的查询
PRODUCER                       FirstQueryColumn       
------------------------------ ---------------------- 
aaaaaaaaaaaa                   1                      
bbbbbbbbbbb                    1                      

PRODUCER                       SecondQueryColumn      
------------------------------ ---------------------- 
aaaaaaaaaaaa                   2                      
bbbbbbbbbbb                    1                      

我想知道的是我应该怎么做才能让我在单个查询中获得相同的数据,也就是说,我想要的东西会产生(Producer, FirstQueryColumn, SecondQueryColumn)

我该怎么做?

以下是我当前的疑问:

select Producers.name Prod, count(Animals.idanimal) AnimalsBought
from AnimalsBought, Animals, Producers
where (AnimalsBought.idanimal = Animals.idanimal) and (Animals.owner = Producers.nif) group by Producers.name;

select Producers.name Prod, count(Animals.idanimal) AnimalsExploration
from AnimalsExploration, Animals, Producers
where (AnimalsExploration.idanimal = Animals.idanimal) and (Animals.owner = Producers.nif) group by Producers.name;

正如您所看到的,对于这种情况,连接不会做太多事情:

select Producers.name Prod, count(AnimalsBought.idanimal) AnimalsBought, count(AnimalsExploration.idanimal) AnimalsExploration
from Producers, Animals, AnimalsBought, AnimalsExploration
where (AnimalsExploration.idanimal = Animals.idanimal) and (Animals.owner = Producers.nif) group by Producers.name;

或者我做错了什么?

9 个答案:

答案 0 :(得分:5)

首先想象2个查询只是表格。你会这样做:

select a.producer, a.firstquerycolumn, b.secondquerycolumn
from table1 a
join table2 b on b.producer = a.producer

您可以通过查询替换每个表(称为内联视图):

select a.Prod, a.AnimalsBought, b.AnimalsExploration
from
( select Producers.name Prod, count(Animals.idanimal) AnimalsBought
  from AnimalsBought, Animals, Producers
  where (AnimalsBought.idanimal = Animals.idanimal) 
  and (Animals.owner = Producers.nif) 
  group by Producers.name
) a
join
( select Producers.name Prod, count(Animals.idanimal) AnimalsExploration
  from AnimalsExploration, Animals, Producers
  where (AnimalsExploration.idanimal = Animals.idanimal) 
  and (Animals.owner = Producers.nif)
  group by Producers.name
) b
on a.Prod = b.Prod;

如果一个查询可能返回生产者的数据而另一个查询不返回,则可能需要将“join”更改为“full outer join”。我也倾向于按如下方式重新构造查询,使生成器外部的主查询连接到2个子查询(删除了生成器):

select Producers.name Prod, a.AnimalsBought, b.AnimalsExploration
from Producers
left outer join ( select Animals.owner, count(AnimalsBought.idanimal) AnimalsBought
                    from AnimalsBought, Animals
                   where AnimalsBought.idanimal = Animals.idanimal
                   group by Animals.owner
                ) a
           on a.owner = Producers.nif
left outer join ( select Animals.owner, count(Animals.idanimal) AnimalsExploration
                    from AnimalsExploration, Animals
                   where AnimalsExploration.idanimal = Animals.idanimal
                   group by Animals.owner
                ) b
           on b.owner = Producers.nif;

(正是这种类型的查询,我测试了下面的表现)。


对于OP可能不感兴趣的信息而不是膨胀这个答案,我关于标量子查询和Oracle内联视图(由PerformanceDBA请求)的相对性能的说明现在在这里离线:Notes on Performance

答案 1 :(得分:4)

select

tab1.producer
tab1.cola
tab2.colb

from
     (query a) tab1
inner join
     (query b) tab2
on
      tab1.producer = tab2.producer

如果每个查询中不存在每个生成器,您可能希望将连接更改为完全外连接。

答案 2 :(得分:3)

我认为animals.idanimal是主键。如果是这样,可以使用左外连接和count在目标列上编写查询以切断NULLs

select producers.name prod,
       count(animalsbought.idanimal) animalsbought,
       count(animalsexploration.idanimal) animalsexploration
from producers
  join animals on  animals.owner = producers.nif
  left join animalsbought on animalsbought.idanimal = animals.idanimal
  left join animalsexploration on animalsexploration.idanimal = animals.idanimal
group by producers.name;

答案 3 :(得分:3)

答案 4 :(得分:1)

我认为这应该是一个单独的答案,因为它与您的原始查询有关,而不是您所说的问题。我正在接受你的 ,或者我做错了什么? 。在其他方面。

由于我和托尼一起锻炼,需要检查你的两套原件,很明显他们效率低下,并且可以改进,如我之前的答案中的(1),(2)所示。考虑和处理您需要解决的Oracle障碍,会干扰并禁止以集合为导向的方法来解决查询。

  1. 所以我们暂时搁置这一点并采取(1),(2)方法。换句话说,如果你从糟糕的苹果开始,而你只是扩展它们(这是你的具体问题),那么这种不良情况会翻两番,如测试中所证明的那样。

  2. 我将大结果集的投影放在一边,然后GROUPing就像你一样。因为你想要一个Producers ++列表,我使用它作为查询的基本结构。然后我用标量子查询填充聚合。 <{1}}和处理该工作表所需的工作表将被删除。

  3. 另一种陈述方式是,我已将您的原始查询规范化。

  4. 我假设你需要加入GROUP BY进行存在检查;否则(因为它未在AnimalsBought中引用),可以将其删除。

  5. 我怀疑它会比原始查询更快,即使我听说Oracle不能很好地处理标量子查询,因为这可以避免处理大集合;但是我不能在Oracle上测试这个。

    COUNT()

    如果这对您有用,那自然会导致您对所述问题的回答:

    SELECT  Producers.name Prod, 
            ( SELECT count(Animals.idanimal)
                  FROM  Animals,
                        AnimalsBought
                  WHERE (p.nif = Animals.owner)
                  AND   (Animals.idanimal = AnimalsBought.idanimal) 
                  ) AnimalsBought
        FROM  Producers p;
    SELECT Producers.name Prod, ( SELECT count(Animals.idanimal) FROM Animals, AnimalsExploration WHERE (p.nif = Animals.owner) AND (Animals.idanimal = AnimalsExploration.idanimal) ) AnimalsExploration FROM Producers p;

    如果你被Nulls和Spinsters所困扰,那么mcha的答案是最好的。

答案 5 :(得分:0)

不考虑查询的细节,我认为以下内容可能有所帮助。

Select A.Producer, A.FirstQueryColumn, B.SecondQueryColumn
From
(
   Select Producer, FirstQueryColumn, '' As SecondQueryColumn
   From TableA
) AS A
Inner Join
(
   Select Producer, '' as FirstQueryColumn, SecondQueryColumn
   From TableA
) AS B ON A.Producer = B.Producer

答案 6 :(得分:0)

SELECT A.producer, COUNT(A.firstquerycolumn), COUNT(B.secondquerycolumn) FROM 
TAB1 A, TAB2 B
WHERE A.producer = B.producer 
GROUP BY A.firstquerycolumn, B.secondquerycolumn

这就是你所要求的?

答案 7 :(得分:0)

我理解的是,您需要一个可以显示的查询:

PRODUCER            FirstQueryColumn       SecondQueryColumn      
------------------------------------------------------------
aaaaaaaaaaaa         1                      2
bbbbbbbbbbb          1                      1
你可以尝试类似的东西:

SELECT (SELECT Producers.name Prod
          FROM AnimalsBought, Animals, Producers
         WHERE (AnimalsBought.idanimal = Animals.idanimal)
           AND (Animals.owner = Producers.nif)
         GROUP BY Producers.name) as Producers,
       (SELECT COUNT(Animals.idanimal) AnimalsBought
          FROM AnimalsBought, Animals, Producers
         WHERE (AnimalsBought.idanimal = Animals.idanimal)
           AND (Animals.owner = Producers.nif)
         GROUP BY Producers.name) as firstQuery,
       (SELECT COUNT(Animals.idanimal) AnimalsExploration
          FROM AnimalsExploration, Animals, Producers
         WHERE (AnimalsExploration.idanimal = Animals.idanimal)
           AND (Animals.owner = Producers.nif)
         GROUP BY Producers.name) as secondQuery
  FROM DUAL

当然你可以优化它,它只是一个想法:)

答案 8 :(得分:0)

你想加入桌子吗? (把桌子放在彼此的顶部)
或者你想加入桌子? (并排放桌子)

union和join都可以生成你想要的输出格式,但却是非常不同的东西。

由于他们的列不匹配,您需要将空占位符插入到联合中。