将2个SQL查询合并为一个

时间:2015-03-15 11:57:52

标签: sql oracle oracle11g

有人可以帮我加入2个查询吗? 基本上它是具有不同子句的相同查询(请注意FIELD3过滤器和子查询中的相关计数器):

SELECT  A.FIELD1,A.FIELD2,A.FIELD3
   FROM 
   TABLE A 
   INNER JOIN
   (
    SELECT FIELD1, COUNT(1) 
    FROM TABLE
    where SUBSTR(FIELD3,1,5)='33377' and
    timestamp between sysdate - interval '20' minute and sysdate - interval '2' minute
    GROUP BY FIELD1
    HAVING COUNT(1) >= 100
    ) B
    ON A.FIELD1 = B.FIELD1 where ...some other clauses who interacts with FIELD4,5,6,etc... ;

SELECT  A.FIELD1,A.FIELD2,A.FIELD3
   FROM 
   TABLE A 
   INNER JOIN
   (
    SELECT FIELD1, COUNT(1) 
    FROM TABLE
    where SUBSTR(FIELD3,1,5)!='33377' and
    timestamp between sysdate - interval '20' minute and sysdate - interval '2' minute
    GROUP BY FIELD1
    HAVING COUNT(1) >= 150
    ) B
    ON A.FIELD1 = B.FIELD1 where ...some other clauses who interacts with FIELD4,5,6,etc... ;

我的目标是什么?让我解释一下。 我有一个带有一些字段的表的Oracle DB,对于这个查询,只需要3个字段,如下所示。 我正在尝试使用多个计数进行查询。我需要的是一个查询,根据FIELD3的前5位数输出超过特定计数的列表。让我举一个具体的例子:

这就是我对数据库的看法:

FIELD1               FIELD2               FIELD3          
1234567314           333776543585218      333771434591151
1234567871           333771451776784      333771432365581
1234567314           333776543585218      333771240553976
1234567314           333776543585218      333773861003473
1234567314           333776543585218      333773861003473
1234567314           333776543585218      333023861003473
1234567314           333776543585218      333023861003473
1234567314           333776543585218      333023861003473
1234567337           333773660813075      333773650804767
1234567137           333773660798439      333771222628311
1234567319           333776543585219      333773660667594
1234567314           333776543585218      333901451463400
1234567314           333776543585218      333901451463400

现在,我想以下列方式输出field1中的数字:

OUTPUT FIELD1 (and related FIELD2 and FIELD3) who are exceeded a COUNT1 (EG: 3) based on FIELD3 having the same 5 first digits (33377)
OUTPUT FIELD1 (and related FIELD2 and FIELD3) who are exceeded a COUNT2 (EG: 10) based on FIELD3 NOT having the same 5 first digits (33377)

因此,在上面的示例中,我的输出将是:

1234567314           333776543585218      333771434591151
1234567314           333776543585218      333771240553976
1234567314           333776543585218      333773861003473
1234567314           333776543585218      333773861003473
1234567314           333776543585218      333023861003473
1234567314           333776543585218      333023861003473
1234567314           333776543585218      333023861003473
1234567314           333776543585218      333901451463400
1234567314           333776543585218      333901451463400

33377 = 4次出现,其他= 5次出现。第一个阈值超过了计数,因此报告所有行。

基本上,上面报告的2个查询工作完美,但我想将它们合并为一个,以最大限度地缩短查询时间并获得独特的输出。

非常感谢。 卢卡斯

4 个答案:

答案 0 :(得分:3)

您应该可以使用分析函数。

SELECT field1, field2, field3
FROM (SELECT t.*,
             SUM(CASE WHEN field3 LIKE '33377%' THEN 1 ELSE 0 END) OVER (PARTITION BY field1) as cnthave,
             SUM(CASE WHEN field3 NOT LIKE '33377%' THEN 1 ELSE 0 END) OVER (PARTITION BY field1) as cntnothave
      FROM TABLE t
      WHERE timestamp between sysdate - interval '20' minute and sysdate - interval '2' minute
     ) t
WHERE (Other conditions here) AND
      (cnthave > 100 or cntnothave > 150);

答案 1 :(得分:2)

要加入两个查询,请使用 UNION https://docs.oracle.com/cd/E17952_01/refman-5.1-en/union.html

在您可以在该页面中找到的示例中,您还可以使用其他列来跟踪您的记录所属的选择。

答案 2 :(得分:0)

使用UNION ALL:

SELECT  A.FIELD1,A.FIELD2,A.FIELD3
   FROM 
   TABLE A 
   INNER JOIN
   (
    SELECT FIELD1, COUNT(1) 
    FROM TABLE
    where SUBSTR(FIELD3,1,5)='33377' and
    timestamp between sysdate - interval '20' minute and sysdate - interval '2' minute
    GROUP BY FIELD1
    HAVING COUNT(1) >= 100
    ) B
    ON A.FIELD1 = B.FIELD1 where ...some other clauses who interacts with FIELD4,5,6,etc...
UNION ALL
SELECT  A.FIELD1,A.FIELD2,A.FIELD3
   FROM 
   TABLE A 
   INNER JOIN
   (
    SELECT FIELD1, COUNT(1) 
    FROM TABLE
    where SUBSTR(FIELD3,1,5)!='33377' and
    timestamp between sysdate - interval '20' minute and sysdate - interval '2' minute
    GROUP BY FIELD1
    HAVING COUNT(1) >= 150
    ) B
    ON A.FIELD1 = B.FIELD1 where ...some other clauses who interacts with FIELD4,5,6,etc... ;

在Oracle UNION中遇到了确保结果集中没有重复项的麻烦,这可能非常耗时。 UNION ALL避免了这个问题。

Reference here

分享并享受。

答案 3 :(得分:0)

组合这两个查询很简单。但有两点建议。首先,使用CTE而不是内联视图。它不会改变性能 - 它看起来更干净,更简洁(imho)。其次,如果您要组合这样的两个查询,请添加一个字段,用于标识每行的原因。使分析师的工作变得更容易。

with
Tablecounts( Field1, Hits, Misses )As(
    Select  Field1,
            Sum( Case When Substr( Field3, 1, 5) = '33377' Then 1 Else 0 End ),
            Sum( Case When Substr( Field3, 1, 5) = '33377' Then 0 Else 1 End )
    From    Table
    Where   Timestamp Between Sysdate - Interval '20' Minute And Sysdate - Interval '2' Minute
    Group By Field1
)
Select  Rd.Field1, Rd.Field2, Rd.Field3,
        case when tc.Hits > 100
             then 'This is a hit'
             else 'This is a miss...or something' end as Why
From    Table     Rd
Join    Tablecounts Tc
    On  Tc.Field1 = Rd.Field1
    and( tc.Hits > 100 or tc.Misses > 150 );

编辑:我使用分析重写了。除了风格上的细微差别外,它与戈登的相同。但戈登回答的评论表明存在问题。它看起来像它应该工作。实际上是否存在问题?如果是,那是什么?

with
Counts( Field1, Field2, Field3, Hits, Misses )As(
    Select  Field1, Field2, Field3,
            Sum( Case When Field3 Like '33377%' Then 1 Else 0 End ) Over( Partition By Field1 ),
            Sum( Case When Field3 Like '33377%' Then 0 Else 1 End ) Over( Partition By Field1 )
    From    Table
    Where   Timestamp Between Sysdate - Interval '20' Minute And Sysdate - Interval '2' Minute
)
Select  Field1, Field2, Field3,
        Case When Hits > 3
             Then 'This is a hit'
             else 'This is a miss...or something' end as Why
From    Counts
where   Hits > 100 or Misses > 150;