将 2 SQL 个查询合并为一个

Join 2 SQL queries into one

有人可以帮我将 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... ;

我的目标是什么?让我解释得更好。 我有一个带有 table 和一些字段的 Oracle 数据库,对于此查询,只需要 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 个查询工作完美,但我想将它们合并为一个以最小化查询时间并获得唯一的输出。

非常感谢。 卢卡斯

要连接两个查询,请使用 UNIONhttps://docs.oracle.com/cd/E17952_01/refman-5.1-en/union.html

正如您可以在该页面中找到的示例一样,您还可以使用一个额外的列来跟踪 select 您的记录属于哪个。

您应该能够为此使用分析函数。

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);

使用 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.

分享和享受。

组合这两个查询非常简单。不过有两个建议。首先,使用 CTE 而不是内联视图。它不会改变性能 - 它只是看起来......更干净,更整洁(恕我直言)。其次,如果您要像这样组合两个查询,请添加一个字段来标识每一行及其存在的原因。让分析师的工作更轻松一些。

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;