3

我真的被这个任务困住了——我需要根据特定的标准用“0”值的行填充报表,下面是示例:

假设我们有一个表 BROKERS,其中包含公司名称、他们的交易类型和当前月份和所有月份的累计金额。

COMPANY       TRAN_TYPE          CURR_MNTH         ALL_MNTH  
Broker1       CURRENCY_SELL      $1000.00          $1500000.00 
Broker1       GOLD_SELL          $50000.00         $2500000.00 
Broker1       GOLD_BUY           $80000.00         $8500000.00 
Broker1       STOCKS_SELL        $35000.00         $3500000.00 

表 BROKERS 没有字段 TRAN_TYPE,但有一个字段 TRAN_TYPE_CD,它引用另一个名为 TRAN_TYPE_CD_EXPL 的表,其中解释了所有代码:

TRAN_TYPE_CD  TRAN_TYPE_CD_EXPLD
1             STOCKS_SELL
2             STOCKS_BUY
3             GOLD_SELL
4             GOLD_BUY
5             SILVER_SELL
6             SILVER_BUY
7             COPPER_SELL
8             COPPER_BUY
9             CURRENCY_SELL
10            CURRENCY_BUY

所以上面显示的结果只是这两个表的简单连接:

select  b.COMPANY, tt.TRAN_TYPE, b.CURR_MONTH, b.ALL_MNTH
from    BROKERS b, TRAN_TYPE_CD_EXPL tt
where   b.TRAN_TYPE_CD = tt.TRAN_TYPE_CD;

一切都很简单,但问题就从这里开始:我正在处理的报告应该如下所示:

COMPANY       MARKET      TRAN_TYPE          CURR_MNTH         ALL_MNTH  
Broker1       FOREX       CURRENCY_SELL      $1000.00          $1500000.00 
Broker1       FOREX       CURRENCY_BUY       $0.00             $5500000.00 
Broker1       CONTRACTS   GOLD_SELL          $50000.00         $2500000.00 
Broker1       CONTRACTS   GOLD_BUY           $80000.00         $8500000.00 
Broker1       STOCKMARKET STOCKS_SELL        $35000.00         $3500000.00 
Broker1       STOCKMARKET STOCKS_BUY         $0.00             $9500000.00 

所以让我解释一下:首先,报告应该包含一个列 MARKET,它应该根据列 TRAN_TYPE 中的值填充,但问题是数据库中没有表 MARKET,所以每次你需要在一个报告或其他地方,您需要像这样使用解码(假设每个人都知道所有类型的 tran_types 属于哪里):

SELECT DECODE (TRAN_TYPE_CD_EXPL.TRAN_TYPE_CD_EXPLD,
             'CURRENCY_SELL', 'FOREX',
             'CURRENCY_BUY', 'FOREX',
             'STOCKS_SELL', 'STOCKMARKET',
             'STOCKS_BUY', 'STOCKMARKET') AS MARKET,

或基于 TRAN_TYPE_CD 值:

SELECT DECODE (BROKERS.TRAN_TYPE_CD,
             9, 'FOREX',
             10, 'FOREX',
             1, 'STOCKMARKET',
             2, 'STOCKMARKET') AS MARKET,

2) 问题 2 更复杂:报告逻辑说 - 公司在特定组中至少有一笔交易(假设市场类型为 'FOREX' 的 CURRENCY_SELL),报告应填充市场类型中的其他 tran_types即使您这家公司在本月没有任何这些交易,也可以用 0 美元分组。所以在这种情况下,它应该填充行

Broker1       FOREX       CURRENCY_BUY       $0.00             $5500000.00

Broker1       STOCKMARKET STOCKS_BUY         $0.00             $9500000.00

问题是它将在 unix 上通过 plsql 批处理执行,因此它必须是单个查询。

非常感谢任何想法和/或建议!

谢谢

附言

它的oracle 11gr2,具有只读角色。

4

4 回答 4

2

查询的第一部分与您的完全一样,只是将市场作为内联表。第二部分通过两次加入市场来添加缺失的行以添加缺失的行,然后减去第一部分中已经存在的行。

WITH Market AS (
  SELECT 9 TRAN_TYPE_CD, 'FOREX' Market FROM dual
  UNION ALL SELECT 10, 'FOREX' FROM dual
  UNION ALL SELECT 1, 'STOCKMarket'  FROM dual
  UNION ALL SELECT 2, 'STOCKMarket' FROM dual
  UNION ALL SELECT 3, 'CONTRACTS' FROM dual
  UNION ALL SELECT 4, 'CONTRACTS' FROM dual
)
SELECT b.COMPANY, Market.Market, tt.TRAN_TYPE_CD_EXPLD, 
       b.CURR_MONTH, b.ALL_MONTH
  FROM BROKERS b 
 INNER JOIN TRAN_TYPE_CD_EXPL tt
    ON b.TRAN_TYPE_CD = tt.TRAN_TYPE_CD
 INNER JOIN Market
    ON b.TRAN_TYPE_CD = Market.TRAN_TYPE_CD
UNION ALL
(
  SELECT b.COMPANY, Market.Market, tt.TRAN_TYPE_CD_EXPLD, 
         0 CURR_MONTH, 0 ALL_MONTH
    FROM BROKERS b 
   INNER JOIN Market
      ON b.TRAN_TYPE_CD = Market.TRAN_TYPE_CD
   INNER JOIN Market Market2
      ON Market.Market = Market2.Market
     AND Market.TRAN_TYPE_CD <> Market2.TRAN_TYPE_CD
   INNER JOIN TRAN_TYPE_CD_EXPL tt
      ON Market2.TRAN_TYPE_CD = tt.TRAN_TYPE_CD
 MINUS
 SELECT b.COMPANY, Market.Market, tt.TRAN_TYPE_CD_EXPLD, 
        0 CURR_MONTH, 0 ALL_MONTH
   FROM BROKERS b 
  INNER JOIN TRAN_TYPE_CD_EXPL tt
     ON b.TRAN_TYPE_CD = tt.TRAN_TYPE_CD
  INNER JOIN Market
     ON b.TRAN_TYPE_CD = Market.TRAN_TYPE_CD
)

这是用于测试结果的Sql Fiddle 。

于 2012-04-16T20:55:34.947 回答
2

首先,您不能创建 MARKET 表是否有原因?这显然是最直接的解决方案。但是,如果您没有数据库访问权限并且必须将其破解到您的查询中,您可以执行以下操作:

WITH m AS (
    select 'CURRENCY_SELL' as tran_type, 'FOREX' as market_name from dual
    UNION ALL
    select 'CURRENCY_BUY' as tran_type, 'FOREX' as market_name from dual
    UNION ALL
    select 'STOCKS_SELL' as tran_type, 'STOCKMARKET' as market_name from dual
    UNION ALL
    select 'STOCKS_BUY' as tran_type, 'STOCKMARKET' as market_name from dual
)
select
    b.company, m.tran_type, m.market_name, 
    nvl(v.curr_month, 0) as curr_month,
    nvl(v.all_mnth, 0) as all_mnth
from
    m
cross join
    (select distinct b.company from brokers) b
left join (
    select b.COMPANY, tt.TRAN_TYPE, b.CURR_MONTH, b.ALL_MNTH
    from    BROKERS b, TRAN_TYPE_CD_EXPL tt
    where   b.TRAN_TYPE_CD = tt.TRAN_TYPE_CD
) v
on v.company = b.company and v.tran_type = m.tran_type;

首先,我使用内联市场视图完成了公司的交叉连接 - 您将获得每家公司的所有这些记录的组合,即使它们不一起存在于 Brokers 表中。我已经执行了左外连接来获取您的数字,因此如果返回 NULL 值(没有相应的记录),它会插入 0。

这可能并不完全正确(例如,我不知道您如何划分月份),但应该为您指明正确的方向。

更新

好的,所以如果我理解正确,您希望将“空”行限制为经纪人在同一市场内至少有一笔交易的交易类型。

我将假设“BROKERS”是当前月份的视图 - 因此,如果表中有记录,则它发生在本月。

所以我们可以删除交叉连接并改为这样做:

WITH m AS (
    select 9 as tran_type_cd, 'FOREX' as market_name from dual
    UNION ALL
    select 10, 'FOREX' as market_name from dual
    UNION ALL
    select 1, 'STOCKMARKET' from dual
    UNION ALL
    select 2, 'STOCKMARKET' from dual
    UNION ALL 
    SELECT 3, 'CONTRACTS' from dual
    UNION ALL 
    SELECT 4, 'CONTRACTS' from dual
)
select
    bm.company, tt.tran_type, m.market_name, 
    nvl(v.curr_month, 0) as curr_month,
    nvl(v.all_mnth, 0) as all_mnth
from
    (select distinct b.company, m.market_name
     from brokers b
     join m on m.tran_type_cd = b.tran_type_cd) bm
join
    m on m.market_name = bm.market_name
join
    TRAN_TYPE_CD_EXPL tt on tt.tran_type_cd = m.tran_type_cd
left join (
    select b.COMPANY, b.tran_type_cd, b.CURR_MONTH, b.ALL_MNTH
    from    BROKERS b
) v
on v.company = bm.company and v.tran_type_cd = m.tran_type_cd;

视图“bm”(我知道,这是一个很好的首字母缩略词选择!)应该为您提供当月与该公司相关的市场的独特列表。然后我又回到了市场视图,以获取与该市场相关的所有交易类型。和以前一样,如果 Brokers 表中没有匹配的记录,我使用左连接将空行填充为 0。

这是 SQL 小提琴:

http://sqlfiddle.com/#!4/2f16e/13

于 2012-04-16T19:13:38.440 回答
1

不确定您将在哪里获取 all_mnth 的数据,因此您应该先弄清楚这一点。让我们知道,然后加入零值应该很容易。下面是我通过问题 1 的测试查询(类似于@Dan A。我“创建”了一个市场“表”):

with brokers as
(
select 'Broker1' company, 9 tran_type_cd, 1000  curr_mnth, 1500000 all_mnth from dual union
select 'Broker1' company, 3 tran_type_cd, 50000 curr_mnth, 2500000 all_mnth from dual union
select 'Broker1' company, 4 tran_type_cd, 80000 curr_mnth, 8500000 all_mnth from dual union
select 'Broker1' company, 1 tran_type_cd, 35000 curr_mnth, 3500000 all_mnth from dual 
)
, tran_type_cd_expl as
(
select 1  TRAN_TYPE_CD, 'STOCKS_SELL'  TRAN_TYPE_CD_EXPLD from dual union
select 2  TRAN_TYPE_CD, 'STOCKS_BUY'  TRAN_TYPE_CD_EXPLD from dual union
select 3  TRAN_TYPE_CD, 'GOLD_SELL'  TRAN_TYPE_CD_EXPLD from dual union
select 4  TRAN_TYPE_CD, 'GOLD_BUY'  TRAN_TYPE_CD_EXPLD from dual union
select 5  TRAN_TYPE_CD, 'SILVER_SELL'  TRAN_TYPE_CD_EXPLD from dual union
select 6  TRAN_TYPE_CD, 'SILVER_BUY'  TRAN_TYPE_CD_EXPLD from dual union
select 7  TRAN_TYPE_CD, 'COPPER_SELL'  TRAN_TYPE_CD_EXPLD from dual union
select 8  TRAN_TYPE_CD, 'COPPER_BUY'  TRAN_TYPE_CD_EXPLD from dual union
select 9  TRAN_TYPE_CD, 'CURRENCY_SELL'  TRAN_TYPE_CD_EXPLD from dual union
select 10  TRAN_TYPE_CD, 'CURRENCY_BUY'  TRAN_TYPE_CD_EXPLD from dual 
)
, market as
(
select 'CURRENCY_BUY'  tran_type_cd_expld, 'FOREX'       market from dual union
select 'CURRENCY_SELL' tran_type_cd_expld, 'FOREX'       market from dual union
select 'GOLD_BUY'      tran_type_cd_expld, 'CONTRACTS'   market from dual union
select 'GOLD_SELL'     tran_type_cd_expld, 'CONTRACTS'   market from dual union
select 'STOCKS_BUY'    tran_type_cd_expld, 'STOCKMARKET' market from dual union
select 'STOCKS_SELL'   tran_type_cd_expld, 'STOCKMARKET' market from dual 
)

select company, market, t.tran_type_cd_expld tran_type, curr_mnth, all_mnth
from brokers b, tran_type_cd_expl t, market m
where b.tran_type_cd = t.tran_type_cd
and t.tran_type_cd_expld = m.tran_type_cd_expld
;
于 2012-04-16T19:59:44.270 回答
0

我相信您可以使用子查询因子添加额外的行(如 SQL Server 中的 CTE)。如果您没有得到答案,我可以在今晚晚些时候尝试更新代码。

于 2012-04-16T19:09:26.107 回答