我有下一个查询,有时对于相同的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
答案 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的行,你就会看到所有这些行;我认为这没问题?