如何查询2个值必须匹配的数据

时间:2017-02-15 12:02:55

标签: sql oracle

(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条款。

为什么我的逻辑失败了?

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

您可以使用以下方式转动表格:

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 aggregation function创建值的集合,并使用SUBMULTISET operator进行集合比较:

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次表格扫描,而上述任何一种选项只会进行一次表扫描。