需要将子查询中使用聚合函数的 Oracle SQL 转换为 SQL Server (T-SQL) 查询
Need to convert the Oracle SQL using aggregate function in subquery to SQL Server (T-SQL) query
Oracle 查询是
SELECT A.BUSINESS_UNIT
, A.EXT_ORG_ID
, A.INVOICE_ID
, A.CONTACT_NAME
, SUM(A.LINE_AMT) AS INVOICE_AMT
, SUM(CASE WHEN A.APPLIED_AMT - Nvl(( SELECT SUM(LINE_AMT) FROM PS_ITEM_LINE_SF WHERE BUSINESS_UNIT = A.BUSINESS_UNIT AND COMMON_ID = A.EXT_ORG_ID AND ITEM_NBR = A.ITEM_NBR AND ITEM_TYPE_CD = A.ITEM_TYPE_CD
AND LINE_AMT*100000+LINE_SEQ_NBR>A.LINE_AMT*100000+A.LINE_SEQ_NBR),0) < 0 THEN A.LINE_AMT
WHEN A.APPLIED_AMT - Nvl(( SELECT SUM(LINE_AMT) FROM PS_ITEM_LINE_SF WHERE BUSINESS_UNIT = A.BUSINESS_UNIT AND COMMON_ID = A.EXT_ORG_ID AND ITEM_NBR = A.ITEM_NBR AND ITEM_TYPE_CD = A.ITEM_TYPE_CD
AND LINE_AMT*100000+LINE_SEQ_NBR>A.LINE_AMT*100000+A.LINE_SEQ_NBR),0) >= A.LINE_AMT THEN 0
ELSE A.LINE_AMT - A.APPLIED_AMT+Nvl(( SELECT SUM(LINE_AMT) FROM PS_ITEM_LINE_SF WHERE BUSINESS_UNIT = A.BUSINESS_UNIT AND COMMON_ID = A.EXT_ORG_ID AND ITEM_NBR = A.ITEM_NBR AND ITEM_TYPE_CD =
A.ITEM_TYPE_CD AND LINE_AMT*100000+LINE_SEQ_NBR>A.LINE_AMT*100000+A.LINE_SEQ_NBR),0) END) AS INVOICE_BALANCE
, 0.0 FROM PS_SIS_SF_EO_INV_V A
GROUP BY A.BUSINESS_UNIT, A.EXT_ORG_ID, A.INVOICE_ID, A.CONTACT_NAME
将 NVL 转换为 ISNULL 时出现以下错误。
"Cannot perform an aggregate function on an expression containing an aggregate or a subquery."于是在网上查了一下,发现必须应用CTE。
我按如下方式转换查询,但查询结果仍然与 Oracle 查询不同。请帮忙。
WITH CTELINE AS (SELECT SUM(B.LINE_AMT) AS LINE_AMT, A.BUSINESS_UNIT FROM PS_ITEM_LINE_SF B, PS_SIS_SF_EO_INV_V A
WHERE B.BUSINESS_UNIT = A.BUSINESS_UNIT AND B.COMMON_ID = A.EXT_ORG_ID AND B.ITEM_NBR = A.ITEM_NBR AND B.ITEM_TYPE_CD = A.ITEM_TYPE_CD
AND B.LINE_AMT*100000 + B.LINE_SEQ_NBR > A.LINE_AMT * 100000 + A.LINE_SEQ_NBR GROUP BY A.BUSINESS_UNIT
),
CTECASE AS (SELECT CASE WHEN C.APPLIED_AMT - ISNULL((SELECT LINE_AMT FROM CTELINE ),0) < 0 THEN C.LINE_AMT
WHEN C.APPLIED_AMT - ISNULL(( SELECT LINE_AMT FROM CTELINE ),0) > = C.LINE_AMT THEN 0
ELSE C.LINE_AMT - C.APPLIED_AMT+ISNULL(( SELECT LINE_AMT FROM CTELINE ),0) END AS CTE_INVOICE_BALANCE
,C.BUSINESS_UNIT,C.EXT_ORG_ID, C.INVOICE_ID FROM PS_SIS_SF_EO_INV_V C, CTELINE CTEL WHERE CTEL.BUSINESS_UNIT = C.BUSINESS_UNIT
GROUP BY C.BUSINESS_UNIT, C.EXT_ORG_ID, C.INVOICE_ID, C.CONTACT_NAME,C.APPLIED_AMT,C.LINE_AMT
)
SELECT A.BUSINESS_UNIT
, A.EXT_ORG_ID
, A.INVOICE_ID
, A.CONTACT_NAME
, SUM(A.LINE_AMT) AS INVOICE_AMT
, SUM(CTE_INVOICE_BALANCE) AS INVOICE_BALANCE
, 0.0
FROM PS_SIS_SF_EO_INV_V A, CTECASE CTEC WHERE CTEC.BUSINESS_UNIT = A.BUSINESS_UNIT AND A.EXT_ORG_ID = CTEC.EXT_ORG_ID AND
A.INVOICE_ID = CTEC.INVOICE_ID
GROUP BY A.BUSINESS_UNIT, A.EXT_ORG_ID, A.INVOICE_ID, A.CONTACT_NAME
您重写原始查询是正确的。它包含三个相同的子查询,写得太复杂了。这是我对查询的看法:
select
business_unit,
ext_org_id,
invoice_id,
contact_name,
sum(line_amt) as invoice_amt,
sum
(
case
when applied_amt < sum_line_amt then line_amt
when applied_amt >= sum_line_amt + line_amt then 0
else line_amt - applied_amt + sum_line_amt
end
) as invoice_balance,
0.0
from
(
select
a.*,
coalesce
(
(
select sum(il.line_amt)
from ps_item_line_sf il
where il.business_unit = a.business_unit
and il.common_id = a.ext_org_id
and il.item_nbr = a.item_nbr
and il.item_type_cd = a.item_type_cd
and il.line_amt * 100000 + il.line_seq_nbr > a.line_amt * 100000 + a.line_seq_nbr
), 0
) as sum_line_amt
from ps_sis_sf_eo_inv_v a
) mydata
group by business_unit, ext_org_id, invoice_id, contact_name;
我保留了原来的 table 别名 A,尽管我不喜欢它,因为它不便于记忆。但是我不知道名字ps_sis_sf_eo_inv_v
的哪一部分应该作为别名,当然。
如果我没有出错,那么这个查询应该和原来的查询完全一样,并且很容易转换。
Oracle 查询是
SELECT A.BUSINESS_UNIT
, A.EXT_ORG_ID
, A.INVOICE_ID
, A.CONTACT_NAME
, SUM(A.LINE_AMT) AS INVOICE_AMT
, SUM(CASE WHEN A.APPLIED_AMT - Nvl(( SELECT SUM(LINE_AMT) FROM PS_ITEM_LINE_SF WHERE BUSINESS_UNIT = A.BUSINESS_UNIT AND COMMON_ID = A.EXT_ORG_ID AND ITEM_NBR = A.ITEM_NBR AND ITEM_TYPE_CD = A.ITEM_TYPE_CD
AND LINE_AMT*100000+LINE_SEQ_NBR>A.LINE_AMT*100000+A.LINE_SEQ_NBR),0) < 0 THEN A.LINE_AMT
WHEN A.APPLIED_AMT - Nvl(( SELECT SUM(LINE_AMT) FROM PS_ITEM_LINE_SF WHERE BUSINESS_UNIT = A.BUSINESS_UNIT AND COMMON_ID = A.EXT_ORG_ID AND ITEM_NBR = A.ITEM_NBR AND ITEM_TYPE_CD = A.ITEM_TYPE_CD
AND LINE_AMT*100000+LINE_SEQ_NBR>A.LINE_AMT*100000+A.LINE_SEQ_NBR),0) >= A.LINE_AMT THEN 0
ELSE A.LINE_AMT - A.APPLIED_AMT+Nvl(( SELECT SUM(LINE_AMT) FROM PS_ITEM_LINE_SF WHERE BUSINESS_UNIT = A.BUSINESS_UNIT AND COMMON_ID = A.EXT_ORG_ID AND ITEM_NBR = A.ITEM_NBR AND ITEM_TYPE_CD =
A.ITEM_TYPE_CD AND LINE_AMT*100000+LINE_SEQ_NBR>A.LINE_AMT*100000+A.LINE_SEQ_NBR),0) END) AS INVOICE_BALANCE
, 0.0 FROM PS_SIS_SF_EO_INV_V A
GROUP BY A.BUSINESS_UNIT, A.EXT_ORG_ID, A.INVOICE_ID, A.CONTACT_NAME
将 NVL 转换为 ISNULL 时出现以下错误。 "Cannot perform an aggregate function on an expression containing an aggregate or a subquery."于是在网上查了一下,发现必须应用CTE。
我按如下方式转换查询,但查询结果仍然与 Oracle 查询不同。请帮忙。
WITH CTELINE AS (SELECT SUM(B.LINE_AMT) AS LINE_AMT, A.BUSINESS_UNIT FROM PS_ITEM_LINE_SF B, PS_SIS_SF_EO_INV_V A
WHERE B.BUSINESS_UNIT = A.BUSINESS_UNIT AND B.COMMON_ID = A.EXT_ORG_ID AND B.ITEM_NBR = A.ITEM_NBR AND B.ITEM_TYPE_CD = A.ITEM_TYPE_CD
AND B.LINE_AMT*100000 + B.LINE_SEQ_NBR > A.LINE_AMT * 100000 + A.LINE_SEQ_NBR GROUP BY A.BUSINESS_UNIT
),
CTECASE AS (SELECT CASE WHEN C.APPLIED_AMT - ISNULL((SELECT LINE_AMT FROM CTELINE ),0) < 0 THEN C.LINE_AMT
WHEN C.APPLIED_AMT - ISNULL(( SELECT LINE_AMT FROM CTELINE ),0) > = C.LINE_AMT THEN 0
ELSE C.LINE_AMT - C.APPLIED_AMT+ISNULL(( SELECT LINE_AMT FROM CTELINE ),0) END AS CTE_INVOICE_BALANCE
,C.BUSINESS_UNIT,C.EXT_ORG_ID, C.INVOICE_ID FROM PS_SIS_SF_EO_INV_V C, CTELINE CTEL WHERE CTEL.BUSINESS_UNIT = C.BUSINESS_UNIT
GROUP BY C.BUSINESS_UNIT, C.EXT_ORG_ID, C.INVOICE_ID, C.CONTACT_NAME,C.APPLIED_AMT,C.LINE_AMT
)
SELECT A.BUSINESS_UNIT
, A.EXT_ORG_ID
, A.INVOICE_ID
, A.CONTACT_NAME
, SUM(A.LINE_AMT) AS INVOICE_AMT
, SUM(CTE_INVOICE_BALANCE) AS INVOICE_BALANCE
, 0.0
FROM PS_SIS_SF_EO_INV_V A, CTECASE CTEC WHERE CTEC.BUSINESS_UNIT = A.BUSINESS_UNIT AND A.EXT_ORG_ID = CTEC.EXT_ORG_ID AND
A.INVOICE_ID = CTEC.INVOICE_ID
GROUP BY A.BUSINESS_UNIT, A.EXT_ORG_ID, A.INVOICE_ID, A.CONTACT_NAME
您重写原始查询是正确的。它包含三个相同的子查询,写得太复杂了。这是我对查询的看法:
select
business_unit,
ext_org_id,
invoice_id,
contact_name,
sum(line_amt) as invoice_amt,
sum
(
case
when applied_amt < sum_line_amt then line_amt
when applied_amt >= sum_line_amt + line_amt then 0
else line_amt - applied_amt + sum_line_amt
end
) as invoice_balance,
0.0
from
(
select
a.*,
coalesce
(
(
select sum(il.line_amt)
from ps_item_line_sf il
where il.business_unit = a.business_unit
and il.common_id = a.ext_org_id
and il.item_nbr = a.item_nbr
and il.item_type_cd = a.item_type_cd
and il.line_amt * 100000 + il.line_seq_nbr > a.line_amt * 100000 + a.line_seq_nbr
), 0
) as sum_line_amt
from ps_sis_sf_eo_inv_v a
) mydata
group by business_unit, ext_org_id, invoice_id, contact_name;
我保留了原来的 table 别名 A,尽管我不喜欢它,因为它不便于记忆。但是我不知道名字ps_sis_sf_eo_inv_v
的哪一部分应该作为别名,当然。
如果我没有出错,那么这个查询应该和原来的查询完全一样,并且很容易转换。