Oracle Self Join检索递归数据

时间:2015-07-09 08:19:11

标签: oracle join inner-join self-join

我有以下架构和数据

segmentid  paramid  paramvalue
103 1   4418

101 1   4834

102 1   5587

104 1   7413

105 1   9965

106 1   7421

107 1   7782

103 2   1990|2000

102 2   2005|2010

105 2   1985|1990

104 2   1981

101 3   F

103 3   M

101 4   M

103 4   S

102 5   SUKKHUR

105 5   LAHORE

106 5   HYDRABAD

107 5   KHAIRPUR

101 5   ISLAMABAD

现在我将输入不同的参数值,如卡拉奇M和出生日期。我想只检索其所有参数都返回true的段id。 如果任何参数失败,则该段应该失败。 下面是我的想法,但如果任何paramvalue为真,我会使用or,但当我and时未检索到数据。

select tpv.* from tblsegment ts , tblsegmentparameter tsp , tblsegmentparamvalue tpv
where ts.segmentid = tpv.segmentid and tsp.parameterid = tpv.paramid
and 
(
(lower(tsp.paramname) like 'city' and tpv.paramvalue = 'KARACHI' and tsp.parameterid = tpv.paramid) 
or
(lower(tsp.paramname) like 'gender' and tpv.paramvalue = 'M') 
or
(lower(tsp.paramname) like 'maritalstatus' and tpv.paramvalue = 'S') 
or
(lower(tsp.paramname) like 'product' and tpv.paramvalue = (select distinct ta.productid  from tblcustchannelacct ta ,tblcustomer tc, tblaccount tta 
where ta.relationship_id = '5327016301000015=5311' and ta.channel_id = '0001' and ta.account_id = tta.account_id and ta.customer_id = tc.customerid )
)
or
(lower(tsp.paramname) like 'dob' and 
  (
   (
    to_char( '1985') between
    to_char( REGEXP_SUBSTR ( tpv.paramvalue, '^[^|]*')) 
    and   

    to_char(REGEXP_SUBSTR( tpv.paramvalue, '*[^|]*$'))   
   ) or
   (
   to_char( '1986') = tpv.paramvalue
   )
  )
)
)
order by tsp.sortorder;

2 个答案:

答案 0 :(得分:0)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE tblsegmentparamvalue ( segmentid,  paramid,  paramvalue ) AS
          SELECT 103, 1,   '4418' FROM DUAL
UNION ALL SELECT 101, 1,   '4834' FROM DUAL
UNION ALL SELECT 102, 1,   '5587' FROM DUAL
UNION ALL SELECT 104, 1,   '7413' FROM DUAL
UNION ALL SELECT 105, 1,   '9965' FROM DUAL
UNION ALL SELECT 106, 1,   '7421' FROM DUAL
UNION ALL SELECT 107, 1,   '7782' FROM DUAL
UNION ALL SELECT 103, 2,   '1990|2000' FROM DUAL
UNION ALL SELECT 102, 2,   '2005|2010' FROM DUAL
UNION ALL SELECT 105, 2,   '1985|1990' FROM DUAL
UNION ALL SELECT 104, 2,   '1981' FROM DUAL
UNION ALL SELECT 101, 3,   'F' FROM DUAL
UNION ALL SELECT 103, 3,   'M' FROM DUAL
UNION ALL SELECT 101, 4,   'M' FROM DUAL
UNION ALL SELECT 103, 4,   'S' FROM DUAL
UNION ALL SELECT 102, 5,   'SUKKHUR' FROM DUAL
UNION ALL SELECT 105, 5,   'LAHORE' FROM DUAL
UNION ALL SELECT 106, 5,   'HYDRABAD' FROM DUAL
UNION ALL SELECT 107, 5,   'KHAIRPUR' FROM DUAL
UNION ALL SELECT 101, 5,   'ISLAMABAD' FROM DUAL;

查询1

WITH segments AS (
  SELECT segmentid
  FROM   tblsegmentparamvalue
  GROUP BY segmentid
  HAVING (   COUNT( CASE WHEN paramid = 1 THEN 1 END ) = 0
         OR  COUNT( CASE WHEN paramid = 1 AND paramvalue = '4834'      THEN 1 END ) > 0 )
  AND    (   COUNT( CASE WHEN paramid = 2 THEN 1 END ) = 0
         OR  COUNT( CASE WHEN paramid = 2 AND '1985' BETWEEN SUBSTR( paramvalue, 1, 4 ) AND SUBSTR( paramvalue, -4 ) THEN 1 END ) > 0 )
  AND    (   COUNT( CASE WHEN paramid = 3 THEN 1 END ) = 0
         OR  COUNT( CASE WHEN paramid = 3 AND paramvalue = 'F'         THEN 1 END ) > 0 )
  AND    (   COUNT( CASE WHEN paramid = 4 THEN 1 END ) = 0
         OR  COUNT( CASE WHEN paramid = 4 AND paramvalue = 'M'         THEN 1 END ) > 0 )
  AND    (   COUNT( CASE WHEN paramid = 5 THEN 1 END ) = 0
         OR  COUNT( CASE WHEN paramid = 5 AND paramvalue = 'ISLAMABAD' THEN 1 END ) > 0 )
)
SELECT t.*
FROM   tblsegmentparamvalue t
       INNER JOIN
       segments s
       ON ( t.segmentid = s.segmentid )
ORDER BY
       t.segmentid,
       paramid

<强> Results

| SEGMENTID | PARAMID | PARAMVALUE |
|-----------|---------|------------|
|       101 |       1 |       4834 |
|       101 |       3 |          F |
|       101 |       4 |          M |
|       101 |       5 |  ISLAMABAD |

答案 1 :(得分:0)

这是一个如何获得三个参数结果的示例:

select segmentid, paramid, paramvalue 
  from (
    select tpv.*, count(distinct paramid) over (partition by tpv.segmentid) cnt
      from tblsegmentparamvalue tpv 
        join tblsegment ts on ts.segmentid = tpv.segmentid
        join tblsegmentparameter tsp on tsp.parameterid = tpv.paramid
      where (lower(tsp.paramname) like 'city' and tpv.paramvalue = 'KARACHI')
         or (lower(tsp.paramname) like 'gender' and tpv.paramvalue = 'M')
         or (lower(tsp.paramname) like 'martialstatus' and tpv.paramvalue = 'S') )
  where cnt = 3

SQLFiddle demo

添加其他参数(dob,product),就像在查询中一样,并将最后一行更改为where cnt=5以获得完整结果。