如何使用 CASE 将 VARCHAR 转换为数字?
How to Convert VARCHAR to a number using CASE?
我正在尝试在下面的查询(这将是另一个更大的查询的子查询)中将 VARCHAR 转换为可以测量为 <0 或 >0 的值 - 不确定要转换成什么值采用。我收到错误 "operand data type is invalid in the sum operator"
这是我第一次遇到这种情况。最终目的是说"when the value is 'L' then return 0, else return 1"另外DEL_INDICATOR
是PO_ITEM
中的一个字段table但是我在SELECT中省略了。
这是更新后的代码:
SELECT G.order_no AS 'GPS_ORDER_#',
G.order_status AS 'GPS_ORDER_STATUS',
G.cst_order_no AS 'GPS_CUSTOMER_PO_#',
H.PO_NUMBER AS 'SAP_PO_#',
P.PO_ITEM_NUMBER,
P.DEL_INDICATOR
FROM
(SELECT order_no,
order_status,
cst_order_no
FROM asagdwpdx_prod.dbo.SimoxOrder1
UNION ALL
SELECT order_no,
order_status,
cst_order_no
FROM asagdwpdx_prod.dbo.SimoxOrder2
UNION ALL
SELECT order_no,
order_status,
cst_order_no
FROM asagdwpdx_prod.dbo.SimoxOrder3) G
JOIN PDX_SAP_USER.dbo.VW_PO_HEADER H ON G.order_no = H.AHAG_NUMBER
JOIN PDX_SAP_USER.dbo.VW_PO_ITEM P ON H.PO_NUMBER = P.PO_NUMBER
WHERE G.order_status = '10'
AND NOT EXISTS (
SELECT P1.PO_NUMBER,
P1.PO_ITEM_NUMBER,
SUM(CASE
WHEN CAST(P1.DEL_INDICATOR AS INT) = 'L'
THEN '0'
ELSE '1'
END AS [SUM_DEL]) AS [SUM]
FROM PDX_SAP_USER.dbo.VW_PO_ITEM P1
WHERE P1.PO_NUMBER = H.PO_NUMBER
GROUP BY P1.PO_NUMBER,
P1.PO_ITEM_NUMBER,
CASE
WHEN P1.DEL_INDICATOR = 'L'
THEN '0'
ELSE '1'
END
HAVING SUM (CASE
WHEN CAST(P1.DEL_INDICATOR AS INT) = 'L'
THEN '0'
ELSE '1'
END) > '0')
1) 在尝试对值求和之前,您需要将 VARCHAR 转换为数字。
2) 如果你只想对 1 列执行聚合,你需要一个 GROUP BY 子句。
3) 您不能在 WHERE 子句中引用表达式别名,您需要使用 HAVING 子句代替。
4) 你不想使用 FLOAT 数据类型,除非你知道与使用 "approximate" 数字数据类型相关的问题。根据 DEL_INDICATOR_CALC 中的数据,考虑使用 INT、DECIMAL 或 NUMERIC。
考虑到这一点,看看下面的方法对你有何作用...
SELECT
vpi.PO_NUMBER,
vpi.PO_ITEM_NUMBER,
CASE WHEN vpi.DEL_INDICATOR = 'L' THEN '0' ELSE '1' END AS 'DEL_INDICATOR_CALC',
SUM(TRY_CONVERT(INT, vpi.DEL_INDICATOR_CALC)) AS 'PO_TYPE'
FROM
dbo.VW_PO_ITEM vpi
GROUP BY
vpi.PO_NUMBER,
vpi.PO_ITEM_NUMBER,
CASE WHEN vpi.DEL_INDICATOR = 'L' THEN 0 ELSE 1 END
HAVING
SUM(TRY_CONVERT(INT, vpi.DEL_INDICATOR_CALC)) = 1;
我认为您没有充分描述您想要的结果,但这里有两个选项可能会让您走上正确的道路:
将 group by
与 having
子句一起使用仅 return po_type > 0
:
select
po_number
, po_item_number
, po_type = sum(case when del_indicator = 'L' then 0 else 1 end)
from vw_po_item
group by
po_number
, po_item_number
having sum(case when del_indicator = 'L' then 1 else 0 end) > 0
将 common table expression(派生的 table 也同样有效)与 sum() over()
聚合 window 函数一起使用:
;with cte as (
select
po_number
, po_item_number
, del_indicator_calc = case when del_indicator = 'L' then 0 else 1 end
, po_type = sum(case when del_indicator = 'L' then 0 else 1 end)
over (partition by po_number, po_item_number)
from vw_po_item
)
select *
from cte
where po_type > 0
根据您打算如何将其用作 "subquery of another larger query",您可能需要考虑使用 exists()
or not exists()
子句:
select ...
from ...
where ...
/* only return records that have an item with del_indicator = 'L' */
and exists (
select 1
from po_item i
where i.po_number = t.po_number -- `t` being an alias for a table in your `from` clause
-- if you are using the subquery per item instead of just `po_number`
and i.po_item_number = t.po_item_number
and del_indicator = 'L'
)
使用示例not exists()
select
G.order_no as [gps_order_#]
, G.order_status as [gps_order_status]
, G.cst_order_no as [gps_customer_po_#]
, H.po_number as [sap_po_#]
, P.po_item_number
, P.del_indicator
from (
select order_no, order_status, cst_order_no
from asagdwpdx_prod.dbo.SimoxOrder1
union all
select order_no, order_status, cst_order_no
from asagdwpdx_prod.dbo.SimoxOrder2
union all
select order_no, order_status, cst_order_no
from asagdwpdx_prod.dbo.SimoxOrder3
) G
inner join pdx_sap_user.dbo.vw_po_header H
on G.order_no = H.ahag_number
inner join pdx_sap_user.dbo.vw_po_item P
on H.po_number = P.po_number
where G.order_status = '10'
and not exists (
select 1
from pdx_sap_user.dbo.vw_po_item i
where i.po_number = H.po_number
and (i.del_indicator <> 'L' or i.del_indicator is null)
)
我正在尝试在下面的查询(这将是另一个更大的查询的子查询)中将 VARCHAR 转换为可以测量为 <0 或 >0 的值 - 不确定要转换成什么值采用。我收到错误 "operand data type is invalid in the sum operator"
这是我第一次遇到这种情况。最终目的是说"when the value is 'L' then return 0, else return 1"另外DEL_INDICATOR
是PO_ITEM
中的一个字段table但是我在SELECT中省略了。
这是更新后的代码:
SELECT G.order_no AS 'GPS_ORDER_#',
G.order_status AS 'GPS_ORDER_STATUS',
G.cst_order_no AS 'GPS_CUSTOMER_PO_#',
H.PO_NUMBER AS 'SAP_PO_#',
P.PO_ITEM_NUMBER,
P.DEL_INDICATOR
FROM
(SELECT order_no,
order_status,
cst_order_no
FROM asagdwpdx_prod.dbo.SimoxOrder1
UNION ALL
SELECT order_no,
order_status,
cst_order_no
FROM asagdwpdx_prod.dbo.SimoxOrder2
UNION ALL
SELECT order_no,
order_status,
cst_order_no
FROM asagdwpdx_prod.dbo.SimoxOrder3) G
JOIN PDX_SAP_USER.dbo.VW_PO_HEADER H ON G.order_no = H.AHAG_NUMBER
JOIN PDX_SAP_USER.dbo.VW_PO_ITEM P ON H.PO_NUMBER = P.PO_NUMBER
WHERE G.order_status = '10'
AND NOT EXISTS (
SELECT P1.PO_NUMBER,
P1.PO_ITEM_NUMBER,
SUM(CASE
WHEN CAST(P1.DEL_INDICATOR AS INT) = 'L'
THEN '0'
ELSE '1'
END AS [SUM_DEL]) AS [SUM]
FROM PDX_SAP_USER.dbo.VW_PO_ITEM P1
WHERE P1.PO_NUMBER = H.PO_NUMBER
GROUP BY P1.PO_NUMBER,
P1.PO_ITEM_NUMBER,
CASE
WHEN P1.DEL_INDICATOR = 'L'
THEN '0'
ELSE '1'
END
HAVING SUM (CASE
WHEN CAST(P1.DEL_INDICATOR AS INT) = 'L'
THEN '0'
ELSE '1'
END) > '0')
1) 在尝试对值求和之前,您需要将 VARCHAR 转换为数字。 2) 如果你只想对 1 列执行聚合,你需要一个 GROUP BY 子句。 3) 您不能在 WHERE 子句中引用表达式别名,您需要使用 HAVING 子句代替。 4) 你不想使用 FLOAT 数据类型,除非你知道与使用 "approximate" 数字数据类型相关的问题。根据 DEL_INDICATOR_CALC 中的数据,考虑使用 INT、DECIMAL 或 NUMERIC。
考虑到这一点,看看下面的方法对你有何作用...
SELECT
vpi.PO_NUMBER,
vpi.PO_ITEM_NUMBER,
CASE WHEN vpi.DEL_INDICATOR = 'L' THEN '0' ELSE '1' END AS 'DEL_INDICATOR_CALC',
SUM(TRY_CONVERT(INT, vpi.DEL_INDICATOR_CALC)) AS 'PO_TYPE'
FROM
dbo.VW_PO_ITEM vpi
GROUP BY
vpi.PO_NUMBER,
vpi.PO_ITEM_NUMBER,
CASE WHEN vpi.DEL_INDICATOR = 'L' THEN 0 ELSE 1 END
HAVING
SUM(TRY_CONVERT(INT, vpi.DEL_INDICATOR_CALC)) = 1;
我认为您没有充分描述您想要的结果,但这里有两个选项可能会让您走上正确的道路:
将 group by
与 having
子句一起使用仅 return po_type > 0
:
select
po_number
, po_item_number
, po_type = sum(case when del_indicator = 'L' then 0 else 1 end)
from vw_po_item
group by
po_number
, po_item_number
having sum(case when del_indicator = 'L' then 1 else 0 end) > 0
将 common table expression(派生的 table 也同样有效)与 sum() over()
聚合 window 函数一起使用:
;with cte as (
select
po_number
, po_item_number
, del_indicator_calc = case when del_indicator = 'L' then 0 else 1 end
, po_type = sum(case when del_indicator = 'L' then 0 else 1 end)
over (partition by po_number, po_item_number)
from vw_po_item
)
select *
from cte
where po_type > 0
根据您打算如何将其用作 "subquery of another larger query",您可能需要考虑使用 exists()
or not exists()
子句:
select ...
from ...
where ...
/* only return records that have an item with del_indicator = 'L' */
and exists (
select 1
from po_item i
where i.po_number = t.po_number -- `t` being an alias for a table in your `from` clause
-- if you are using the subquery per item instead of just `po_number`
and i.po_item_number = t.po_item_number
and del_indicator = 'L'
)
使用示例not exists()
select
G.order_no as [gps_order_#]
, G.order_status as [gps_order_status]
, G.cst_order_no as [gps_customer_po_#]
, H.po_number as [sap_po_#]
, P.po_item_number
, P.del_indicator
from (
select order_no, order_status, cst_order_no
from asagdwpdx_prod.dbo.SimoxOrder1
union all
select order_no, order_status, cst_order_no
from asagdwpdx_prod.dbo.SimoxOrder2
union all
select order_no, order_status, cst_order_no
from asagdwpdx_prod.dbo.SimoxOrder3
) G
inner join pdx_sap_user.dbo.vw_po_header H
on G.order_no = H.ahag_number
inner join pdx_sap_user.dbo.vw_po_item P
on H.po_number = P.po_number
where G.order_status = '10'
and not exists (
select 1
from pdx_sap_user.dbo.vw_po_item i
where i.po_number = H.po_number
and (i.del_indicator <> 'L' or i.del_indicator is null)
)