评估不在分组依据中的列

时间:2016-03-23 15:04:50

标签: sql oracle

我想以某种方式评估一个名为GL的列,当它不在使用Oracle 12c的GROUP BY语句中时。我不想将它包含在GROUP BY中,因为它将为GL中的每个不同数字输出一行。但是,我需要能够判断输出中是否有GL列表。

这些是包含我需要与结果进行比较的GL的样本表:

select asset_appv_acct, purch_accts, legal_accts
  from ap_settings

每个的样本内容:

ASSET_APPV_ACCT:17101,17102,17112,17151,17161,52602,52467,18005,18010,18011,18014,18015,18041,18042,18043,18044,18045,18046,18047,18048,18049,18050,18052,18053,18054,18055,18056,18057,18058,18059,18060
PURCH_ACCTS: 52402,52407,52460,52639
LEGAL_ACCTS: 52608,52615,52616,52617,52618,52621,52626,52635,52636,52659,52662,52663,52664,52680,52682,52683,52684,52685

以下是查询示例:

SELECT h.h_spa_id as spa_id,h.submit_dt,h.oa_ap_date,SomeAggregateFunction()
  FROM table1 h,table2 d, table3
  WHERE h.next_apprv= 'approverID'
    and h.table1_id = d.table2_id
    and h.table1_id = table3_id
  group by h.h_spa_id,h.submit_dt,h.oa_ap_date
  order by h.h_spa_id

这是结果的一个例子:

1627005 1/25/2008 10:11:53 AM 1/25/2008 11:15:56 AM (Result of Aggregate Function Here)

我想评估上面的列表,从子查询或其他东西动态输入,并输出指标字段。例如,如果GL在列表中,则输出1,如果不在列表中则输出0。

诀窍是我需要检查table2中的GL字段,但不要将它包含在GROUP BY子句中。

注意:我尝试了CASE和DECODE。 DECODE没有比较列表中的项目,只是整个列表。所以我总是得到'不匹配'的情景。 CASE似乎很笨拙,因为我必须从列表中单独提取每个GL并为语法创建一个新的案例,比如

WHEN '18327' THEN '*'
WHEN '52407' THEN '*'
WHEN '52460' THEN '*'

将这些列表作为同一结果集的一部分进行查询并评估GL的简便方法是什么?

1 个答案:

答案 0 :(得分:0)

如果我理解你在做什么,你可以左连接到你的查找表,查看GL值是否存在于任何列中,这将为每行提供0/1标志;然后将其与max()汇总。如果您正在分组的行的任何 GL确实匹配,那么您将获得1,否则您将获得0。

类似的东西:

SELECT h.h_spa_id as spa_id,h.submit_dt,h.oa_ap_date,SomeAggregateFunction(),
         max(case when ap.gl is null then 0 else 1 end) as flag
FROM table1 h
JOIN table2 d
ON d.table2_id = h.table1_id
JOIN table3
ON table3_id = h.table1_id
LEFT JOIN (
  SELECT asset_appv_acct AS gl
  FROM ap_settings
  UNION
  SELECT purch_accts
  FROM ap_settings
  UNION
  SELECT legal_accts
  FROM ap_settings
) ap
ON ap.gl = d.gl
WHERE h.next_apprv= 'approverID'
GROUP BY h.h_spa_id,h.submit_dt,h.oa_ap_date
ORDER BY h.h_spa_id

我已经切换到'现代'连接语法,因为它通常更容易,但外连接更简单。

我还加入了查找表中三列的联合,而不是加入表的三个副本,以使case语句更简单。

假设你所展示的是来自不同行的值列表,但是不同数量的值表明你可能在一列中有一个以逗号分隔的字符串 - 这是一个可怕的设计。如果是这种情况,那么您需要更改子查询以标记值;或者你可以使用正则表达式搜索三个字符串中的每个字符串中的每个table2.gl值,但这可能会比一次标记整个批次更慢,更昂贵(因为必须为每个值完成)

从评论中可以看出,您确实有逗号分隔的列表,不仅在ap_settings表中,而且在table2.gl列中。这让它变得混乱。您需要对两者进行标记,例如:

SELECT h.h_spa_id as spa_id,h.submit_dt,h.oa_ap_date,SomeAggregateFunction(),
         max(case when ap.gl is null then 0 else 1 end) as flag
FROM table1 h
JOIN (
  SELECT table2_id, regexp_substr(gl, '[^,]+', 1, level) AS gl
  FROM table2
  CONNECT BY regexp_substr(gl, '[^,]+', 1, level) IS NOT NULL
  AND PRIOR table2_id = table2_id
  AND PRIOR dbms_random.value IS NOT NULL
) d
ON d.table2_id = h.table1_id
JOIN table3
ON table3_id = h.table1_id
LEFT JOIN (
  SELECT regexp_substr(asset_appv_acct, '[^,]+', 1, level) AS gl
  FROM ap_settings
  CONNECT BY regexp_substr(asset_appv_acct, '[^,]+', 1, level) IS NOT NULL
  UNION
  SELECT regexp_substr(purch_accts, '[^,]+', 1, level) AS gl
  FROM ap_settings
  CONNECT BY regexp_substr(purch_accts, '[^,]+', 1, level) IS NOT NULL
  UNION
  SELECT regexp_substr(legal_accts, '[^,]+', 1, level) AS gl
  FROM ap_settings
  CONNECT BY regexp_substr(legal_accts, '[^,]+', 1, level) IS NOT NULL
) ap
ON ap.gl = d.gl
WHERE h.next_apprv= 'approverID'
GROUP BY h.h_spa_id,h.submit_dt,h.oa_ap_date
ORDER BY h.h_spa_id;

但是你现在有多行,所以你需要仔细查看SomeAggregateFunction()实际在做什么,这样才能得到正确的结果......