查询Oracle消除0数量

时间:2015-10-14 14:39:02

标签: sql oracle

我有下一个查询,有时对于相同的id,客户和名称我得到一个数量的市场价值和另一个数量为0的市场价值。如何修改查询以获得数量的市场价值而不是数量0?

SELECT p.ID_CLIENT, p.CLIENT, p.NAME, h.MARKET_VALUE
FROM HOLDING h
INNER JOIN PORTFOLIO p ON h.PF_ID = p.PF_ID 
WHERE
    TO_CHAR (h.DATE, 'DD/MM/YYYY') = ? 
    AND NVL (p.PF_ID, '') = ? 
    AND NVL (h.TYPE, '') NOT IN 'Master'
    AND NVL (h.INSTRUMENT, '') NOT IN 'FX'

我现在的输出是:

ID_CLIENT   CLIENT  NAME    MARKET_VALUE
207        Momentum AAA 0
207        Momentum AAA 3514.11
207        Momentum BBB 0
207        Momentum CCC 84289.84
207        Momentum CCC 358.74

我想要的是:

ID_CLIENT   CLIENT  NAME    MARKET_VALUE
207        Momentum AAA 3514.11
207        Momentum BBB 0
207        Momentum CCC 84289.84
207        Momentum CCC 358.74

3 个答案:

答案 0 :(得分:0)

  

如何修改查询以仅获取数量而非数量0的市场价值?

这在SQL中非常简单直接。

market_value > 0

只有在您拥有NULL值时才需要 NVL

NVL(market_value, 0) > 0

您的代码还有其他一些问题:

  

TO_CHAR(h.DATE,' DD / MM / YYYY')=?

切勿使用 TO_CHAR 来比较日期。正确的方法是将日期列保持原样,并在R.H.S上使用 TO_DATE 。将文字转换为 DATE

根据您的查询,您最终会将 STRING ?占位符中的值所具有的数据类型进行比较。但是,在与日期进行比较时,您应该保留 DATE数据类型

  

AND NVL(h.TYPE,'')NOT IN' Master'

     

AND NVL(h.INSTRUMENT,'')NOT IN' FX'

这在语法上是不正确的。 IN NOT IN 表达式必须包含在括号中。

事实上,在您的情况下,您根本不需要 IN 运算符。只需使用 EQUAL =运算符。

  

AND NVL(h.TYPE,'')

另一个问题,

在Oracle中,''NULL被认为是相似的。这意味着,零长度字符串被视为NULL值。

所以,你的表达式就像说,将NULL视为NULL以与实际值进行比较。哪个永远都是假的

更新

基于OP的新更新,如下所示:

  

我现在的输出是:

ID_CLIENT   CLIENT  NAME    MARKET_VALUE
207        Momentum AAA 0
207        Momentum AAA 3514.11
207        Momentum BBB 0
207        Momentum CCC 84289.84
     

我想要的是:

ID_CLIENT   CLIENT  NAME    MARKET_VALUE
207        Momentum AAA 3514.11
207        Momentum BBB 0
207        Momentum CCC 84289.84

您只需使用 MAX 作为聚合函数以及 GROUP BY

答案 1 :(得分:0)

当且仅当另一行不存在时,您需要环顾其他行并抛弃零市值:

with q as (
    SELECT p.ID_CLIENT, p.CLIENT, p.NAME, h.MARKET_VALUE
    FROM HOLDING h
    INNER JOIN PORTFOLIO p ON h.PF_ID = p.PF_ID 
    WHERE /* I'll let you fix this part */
        TO_CHAR (h.DATE, 'DD/MM/YYYY') = ? 
        AND NVL (p.PF_ID, '') = ? 
        AND NVL (h.TYPE, '') NOT IN 'Master'
        AND NVL (h.INSTRUMENT, '') NOT IN 'FX'
)
select * from q
where MARKET_VALUE <> 0 or not exists (
    select 1 from q q2
    where /* I'm not entirely sure if this is your primary key */
            q2.ID_VALUE = q1.ID_VALUE
        and q2.CLIENT = q1.CLIENT
        and q2.NAME = q.NAME
        and q2.MARKET_VALUE <> 0
)

我在比较中使用的不相同,尽管我想你的所有值都可能是非负的。

答案 2 :(得分:0)

因此,如果每个组的最大市场价值为0,那么您需要解决这个问题,然后相应地进行过滤,例如:

with sample_data as (select 207 id_client, 'Momentum' client, 'AAA' name, 0 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'AAA' name, 3514.11 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'BBB' name, 0 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'CCC' name, 84289.84 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'CCC' name, 358.74 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'DDD' name, 8289.24 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'DDD' name, 38.76 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'DDD' name, 0 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'EEE' name, 0 market_value from dual union all
                     select 207 id_client, 'Momentum' client, 'EEE' name, 0 market_value from dual),
-- end of mimicking the results of your query
             res as (select id_client,
                            client,
                            name,
                            market_value,
                            max(market_value) over (partition by id_client, name) max_market_value
                     from   sample_data)
select id_client,
       client,
       name,
       market_value
from   res
where  max_market_value = 0
or     (max_market_value != 0 and market_value != 0);

 ID_CLIENT CLIENT   NAME MARKET_VALUE
---------- -------- ---- ------------
       207 Momentum AAA       3514.11
       207 Momentum BBB             0
       207 Momentum CCC      84289.84
       207 Momentum CCC        358.74
       207 Momentum DDD       8289.24
       207 Momentum DDD         38.76
       207 Momentum EEE             0
       207 Momentum EEE             0

这意味着您的查询类似于:

select id_client,
       client,
       name,
       market_value
from   (select p.id_client,
               p.client,
               p.name,
               h.market_value,
               max(h.market_value) over (partition by p.id_client, p.name) max_market_value
        from   holding h
               inner join portfolio p on (h.pf_id = p.pf_id)
        where  h.date = to_date(:p_date_string, 'DD/MM/YYYY')
        and    p.pf_id = :p_pf_id 
        and    nvl (h.type, '{NULL}') not in ('Master')
        and    nvl (h.instrument, '{NULL}') not in ('FX'))
where  max_market_value = 0
or     (max_market_value != 0 and market_value != 0);

N.B。从上面的结果可以看出,如果有多个市场价值为0的行,你就会看到所有这些行;我认为这没问题?