使用包含和排除值

时间:2017-11-23 16:14:15

标签: sql hana

我正在尝试查询一个表,并根据另一个包含include和exclude条件的表从中获取一些值。

我有这样的主表:

ColA
600000
675100
123000

标准表如下:

Value | Type
6%    | I
67%   | E

其中%充当外卡。

结果表应为:

ColA
600000

我已经让它得到了正确的结果:

select * 
    from main
    inner join criteria inc
        on ColA like inc.value
        and inc.type = 'I'
    left outer join criteria exc
        on ColA like exc.value
        and exc.type = 'E'
    where exc.value is null
    ;

但是我希望我能在不必查询条件表两次的情况下得到它,因为在创建它时会涉及一些计算。

我想这只是一个可能的性能提升问题,但我认为要求社区没有害处!

谢谢大家!

修改

正如评论中所提到的,我设法将条件表纳入范围。我使用此查询完成了(期望10位数字):

select  case
            when type = 'I'
                then low
            when type = 'E'
                then low_1
        end as low,
        case
            when lead(type) over (order by low asc) = 'E'
                then case
                    when type = 'I' and high < lead(low) over (order by low asc)
                        then high
                    else lead(high_1) over (order by low asc) end
            when type = 'I'
                then high
            else
                max_high
        end as high
    from (
        select  *,
                rpad(digits,10,9) as high,
                rpad(digits+1,10,0) as low_1,
                rpad(digits-1,10,9) as high_1
            from (
                select  main.*,
                        max( for_max_high ) as max_high
                    from (
                        select  type,
                                replace(value,'%','') as digits,
                                rpad(replace(value,'%',''),10,0) as low
                            from criteria
                        ) main
                    left outer join (
                        select  replace(value,'%','') as digits,
                                rpad(replace(value,'%',''),10,9) as for_max_high
                            from criteria
                            where type = 'I'
                    ) for_max
                        on  main.low > rpad(for_max.digits,10,0)
                        and main.type = 'E'
                    group by type, main.digits, low
            )
    )
;

我希望这对某人有用!

2 个答案:

答案 0 :(得分:1)

在大多数数据库中,您可以使用WITH子句。 HANA是否支持WITH子句/ CTE?

见下面的例子。该过程获取一次数据并根据您的喜好使用它。这将提高性能。

WITH v_criteria AS
(
 SELECT type, value 
   FROM criteria 
  WHERE type IN ('I', 'E') 
)
select * 
    from main
    inner join v_criteria inc
        on ColA like inc.value
        and inc.type = 'I'
    left outer join v_criteria exc
        on ColA like exc.value
        and exc.type = 'E'
    where exc.value is null
    ;

答案 1 :(得分:1)

虽然SAP HANA确实支持公用表表达式(CTE,WITH子句),但它对查询的性能没有帮助。

使用EXPLAIN PLAN,您可以看到HANA对所提到的两种查询方式使用完全相同的执行计划。

OPERATOR_NAME                       OPERATOR_DETAILS                                    TABLE_NAME
ROW SEARCH                          MAIN.COLA, INC.TYPE, INC.VALUE, INC.TYPE, INC.VALUE ?
  FILTER                            INC.VALUE IS NULL                                   ?
    NESTED LOOP JOIN (LEFT OUTER)   JOIN CONDITION: MAIN.COLA LIKE INC.VALUE            ?
      NESTED LOOP JOIN              JOIN CONDITION: MAIN.COLA LIKE INC.VALUE            ?
        COLUMN SEARCH               MAIN.COLA                                           ?
          COLUMN TABLE                                                                  MAIN
        COLUMN SEARCH               INC.VALUE, INC.TYPE                                 ?
          COLUMN TABLE              FILTER CONDITION: INC.TYPE = 'I'                    CRITERIA
      COLUMN SEARCH                 INC.VALUE, INC.TYPE                                 ?
        COLUMN TABLE                FILTER CONDITION: INC.TYPE = 'E'                    CRITERIA

使用此计划需要注意的是,它使用两个嵌套连接,并且两个连接都是NESTED LOOP JOINS。 对于提供的最小数据集,这不会有什么坏处,只需将表内容扩展到100.000条记录(main)和200,000条记录(criteria)就会将您的数据库发送到一个冗长的CPU时间盛宴中。 / p>

有效地,系统必须对LIKE联接中的每次迭代运行NL比较。
根据数据,这可以将n * m个记录反馈到外部循环中,这又可以匹配m个匹配

n x m x m LIKE比较=&gt; O(n ^ 3)

或者,您可以使用以下基于集合的查询:

/* include these */
    select 
          main.cola
    from 
                 main 
     inner join criteria cr_in
     on main.ColA like cr_in.value
     and cr_in.type = 'I'
MINUS
 /* exlude these */  
    select 
          main.cola
    from 
                 main 
     inner join criteria cr_in
     on main.ColA like cr_in.value
     and cr_in.type = 'E';

这导致以下执行计划:

OPERATOR_NAME               OPERATOR_DETAILS                                           TABLE_NAME
ROW SEARCH                  MAIN.COLA                                                  ?
  DISTINCT                  GROUPING: MAIN.COLA                                        ?
    HASH JOIN (ANTI SEMI)   HASH BUILD: RIGHT, JOIN CONDITION: MAIN.COLA = MAIN.COLA   ?
      NESTED LOOP JOIN      JOIN CONDITION: MAIN.COLA LIKE CR_IN.VALUE                 ?
        COLUMN SEARCH       MAIN.COLA                                                  ?
          COLUMN TABLE                                                                 MAIN
        COLUMN SEARCH       CR_IN.VALUE                                                ?
          COLUMN TABLE      FILTER CONDITION: CR_IN.TYPE = 'I'                         CRITERIA
      NESTED LOOP JOIN      JOIN CONDITION: MAIN.COLA LIKE CR_IN.VALUE                 ?
        COLUMN SEARCH       MAIN.COLA                                                  ?
          COLUMN TABLE                                                                 MAIN
        COLUMN SEARCH       CR_IN.VALUE                                                ?
          COLUMN TABLE      FILTER CONDITION: CR_IN.TYPE = 'E'                         CRITERIA

显然,两个NESTED LOOP JOINS仍然存在,但没有相互嵌套。合并HASH JOIN使用两个NESTED LOOP联接的结果集,每个联合运行一次。

这里我们最终得到了

的运行时上限
  • 2 x(n x m)(对于两个NESTED LOOP JOINS
  • 2 * m(HASH JOIN

=&GT; O(n ^ 2)

这比以前好(并且两个NL并行执行),但仍然不是很好。
特别是criteria中的大型集合,您希望寻找更好的解决方案。

如果您坚持使用当前的设计方法,一种选择是在插入新条件时检查潜在的较短条件并将其保存在附加列中。

根据您希望支持的标准维护操作的类型,此任务可以变得非常复杂(例如,删除最短的条件到目前为止意味着需要找到新的最短条件并且需要更新保存的引用。

总计:在连接条件中要非常小心“动态”LIKE运算符。