[英]How to query data where 2 values must match
(Oracle 11g)
我有一个查询返回。
OrderNo MyCode Value
1234 AAA 11
1234 BBB PPP
4732 AAA 11
5555 BBB PPP
我的规则的一部分只是在AAA和BBB值匹配的OrderNo处拉回结果。 (即,我知道AAA应该是111,BBB应该是PPP)。
因此,从上面的示例中,我应该只返回OrderNo 1234
我正在努力的地方是设置查询以满足此条件。
目前,我的where子句中包含以下代码:
AND (
-- Match AAA and BBB values.
AJO.VALUE IN (SELECT VALUE FROM SOME_TABLE WHERE S_FILTER IN (SELECT * FROM TABLE(listFilters)) AND AJO.O_FILTER = 'AAA' )
AND
AJO.VALUE IN (SELECT VALUE FROM SOME_TABLE WHERE S_FILTER IN (SELECT * FROM TABLE(listFilters)) AND AJO.O_FILTER = 'BBB' )
)
如果我注释掉第一部分,则得到所有匹配的BBB值的结果,反之亦然,如果我注释掉BBB子句,则相反。
为什么我的逻辑使我失望?
在AND
子句之间AND
结果为空集(因为不能同时为AJO.O_FILTER = 'AAA'
和AJO.O_FILTER = 'BBB'
)。 您需要OR
:
AJO.VALUE IN (SELECT VALUE FROM SOME_TABLE WHERE S_FILTER IN (SELECT * FROM TABLE(listFilters)) AND AJO.O_FILTER = 'AAA' )
OR
AJO.VALUE IN (SELECT VALUE FROM SOME_TABLE WHERE S_FILTER IN (SELECT * FROM TABLE(listFilters)) AND AJO.O_FILTER = 'BBB' )
您可以使用以下数据透视表:
SELECT *
FROM your_table
PIVOT ( MAX( value ) FOR mycode IN ( 'AAA' AS AAA, 'BBB' AS BBB )
这将给:
ORDERNO AAA BBB
------- --- ---
1234 11 PPP
4732 11
5555 PPP
然后,您可以执行以下操作:
SELECT *
FROM (
SELECT *
FROM your_table
PIVOT ( MAX( value ) FOR mycode IN ( 'AAA' AS AAA, 'BBB' AS BBB )
)
WHERE AAA MEMBER OF listFilters
AND BBB MEMBER OF listFilters;
这将给:
ORDERNO AAA BBB
------- --- ---
1234 11 PPP
替代方案 :
您还可以使用COLLECT
聚合函数创建值的集合,并使用SUBMULTISET
运算符进行设置比较:
SELECT OrderNo
FROM (
SELECT OrderNo,
CAST( COLLECT( value ) AS your_listFilter_Type ) AS vals
FROM your_table
WHERE myCode IN ( 'AAA', 'BBB' )
GROUP BY OrderNo
)
WHERE listFilters SUBMULTISET OF vals;
备选方案2 :
SELECT orderno, mycode, value
FROM (
SELECT t.*,
CAST(
COLLECT(
CASE WHEN mycode IN ( 'AAA', 'BBB' ) THEN value END
) OVER ( PARTITION BY OrderNo )
AS your_listFilter_type
) AS vals
FROM your_table t
)
WHERE 1 = 1 -- Some conditions
AND listFilters SUBMULTISET OF vals
AND 2 = 2; -- Some more conditions
为什么我的逻辑使我失望?
您不限制子查询具有与外部查询相同的OrderNo
。
SELECT *
FROM your_table t
WHERE EXISTS( SELECT 1
FROM your_table x
WHERE x.orderno = t.orderno
AND x.mycode = 'AAA'
AND x.value MEMBER OF listFilters )
AND EXISTS( SELECT 1
FROM your_table x
WHERE x.orderno = t.orderno
AND x.mycode = 'BBB'
AND x.value MEMBER OF listFilters );
但是,这可能会进行3次表扫描,而以上两个选项中的任何一个都只会进行一次表扫描。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.