如何使用CASE将VARCHAR转换为数字?

时间:2017-09-24 02:20:33

标签: sql sql-server casting type-conversion varchar

我正在尝试下面的查询(这将是另一个更大的查询的子查询)将VARCHAR转换为可以测量为< 0或> 0的值 - 不确定究竟是什么值使用。我收到错误"operand data type is invalid in the sum operator"这是我第一次遇到这个错误。最终目标是说"当价值是' L'然后返回0,否则返回1"另外DEL_INDICATORPO_ITEM表中的一个字段,但我在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')

2 个答案:

答案 0 :(得分:2)

我认为您没有充分描述您想要的结果,但这里有两个选项可能会让您走上正确的道路:

group byhaving子句一起使用仅返回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(派生表也可以使用sum() over()聚合窗口函数:

;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

根据您计划将其用作“其他较大查询的子查询”的方式,您可能需要考虑使用exists()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)
  )

答案 1 :(得分:0)

1)您需要在尝试对值求和之前将VARCHAR转换为数字。 2)如果要仅对1列执行聚合,则需要GROUP BY子句。 3)您不能在WHERE子句中引用表达式别名,您需要使用HAVING子句。 4)除非您意识到与使用&#34;近似&#34;相关的问题,否则您不想使用FLOAT数据类型。数字数据类型。根据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;