将 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 个查询工作完美,但我想将它们合并为一个以最小化查询时间并获得唯一的输出。
非常感谢。
卢卡斯
要连接两个查询,请使用 UNION:https://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 避免了这个问题。
分享和享受。
组合这两个查询非常简单。不过有两个建议。首先,使用 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;
有人可以帮我将 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 个查询工作完美,但我想将它们合并为一个以最小化查询时间并获得唯一的输出。
非常感谢。 卢卡斯
要连接两个查询,请使用 UNION:https://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 避免了这个问题。
分享和享受。
组合这两个查询非常简单。不过有两个建议。首先,使用 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;