【问题标题】:Case in Where clause not working properly on Teradata?Where 子句在 Teradata 上无法正常工作的案例?
【发布时间】:2020-03-15 12:35:48
【问题描述】:

谁能告诉我我的查询出了什么问题。我肯定知道我在 where 子句中的 case 语句肯定有问题。如果没有 Case 语句,此查询将运行良好。

错误 - 选择失败。 3707: 语法错误,应有类似‘END 关键字在‘)’和“>=”之间的内容

SELECT 
    mp.chnl_name AS mp_channel,
    fsk.sku_prod_id AS pro_id,
    fsk.dateint  AS avlbl_dt,
    fsk.sku_num AS sku,
    fsk.upc_txt AS UPC,
    Coalesce(fsk.brand_name,'N/A') AS brand,
    fsk.ruckload AS LTL_Flag,
    fsk.price_amt AS item_selling_price,
    fsk.on_hand_unit_qty AS qoh,
    fsk.netpropt AS profite,
    (fsk.price_amt  + fsk.shpg_amt) AS lms,
    (GP)*100 AS net_pct
FROM EDW.ITEM_AVLBL mp
JOIN EDW.FULL_SKU fsk ON mp.item_id = fsk.item_id
JOIN  EDW.SHORT_SKU ssk ON ssk.sh_sku_id = fsk.sh_sku_id
WHERE 1=1
    AND mp.chnl_name  LIKE '%google%'  ---------- This is a prompt but I hard coded to test
    AND fsk.item_create_dt >=  '2019-10-20'
    AND  net_pct >= 10
    AND CASE WHEN mp.chnl_name  = 'CA_FACEBOOK'  THEN  ((GP)*100)  >= 7 ELSE  fsk.first_cost > 500 END
GROUP BY 1,2,3,4,5,6,7,8,9,10,11,fsk.first_cost

谁能告诉我如何解决这个问题?

【问题讨论】:

  • 改用 AND/OR 结构。更容易优化。
  • @jarlh 我只需要我的案例条件在 Facebook 上工作。这就是为什么我提出案例条件。知道为什么我会出错吗?

标签: sql teradata teradata-sql-assistant


【解决方案1】:

这里的case在哪里不起作用,你可以重写使用ANDs和ORs

AND ( (mp.chnl_name  = 'CA_FACEBOOK' AND ((GP)*100)  >= 7 ) 
    OR (mp.chnl_name  != 'CA_FACEBOOK' AND fsk.first_cost > 500) ) 

根据您在下面所说的将以下内容添加到 where:

AND ( (mp.chnl_name  = 'CA_FACEBOOK' AND ((GP)*100)  >= 7 AND fsk.first_cost > 500)
      OR mp.chnl_name  != 'CA_FACEBOOK'
    ) 

【讨论】:

  • 只有当它等于 Facebook 时我才需要这个条件。这就是为什么它处于案例状态。这是否按我想要的方式工作?通常,他们会插入谷歌、推特而不是 Facebook。如果是 google 或 twitter 案例条件应该影响我的报告。有意义吗?
  • 当唯一的 mp.chnl_name = 'CA_FACEBOOK' 时我需要这两个条件
  • @WeldaSudha - 这与案例条件的逻辑相同如果您有不同的逻辑,那么您应该解释它是什么。
  • 可能我把你们弄糊涂了。我所需要的只是当他们进入 Facebook(他们可以输入 google、twitter 等提示符)然后我的 `((GP)*100) >= 7` 和 `fsk.first_cost > 500`,这是 Facebook 的附加过滤条件.我在下面尝试过,它可以工作,但是当我们在代码mp.chnl_name LIKE '%google%' 中输入谷歌时,它什么也没给我。 HAVING (CASE WHEN mp.chnl_name = 'CA_FACEBOOK' AND ((GP)*100) >= 7 THEN 1 ELSE 0 END) = 1 AND(CASE WHEN mp.chnl_name = 'CA_FACEBOOK' AND fsk.first_cost > 500 THEN 1 ELSE 0 END) = 1
  • 所以@WeldaSudha 如果他们进入 facebook 但没有这些值,那么您不想包含这些结果吗?如果是这样,那么您不需要案例。
【解决方案2】:

这可能是你想要的:

WHERE 
  (mp.chnl_name <> 'CA_FACEBOOK' 
    AND mp.chnl_name  LIKE '%google%'  ---------- This is a prompt but I hard coded to test
    AND fsk.item_create_dt >=  '2019-10-20'
    AND  net_pct >= 10
OR (( mp.chnl_name  = 'CA_FACEBOOK' AND GP*100  >= 7 AND fsk.first_cost > 500)) 

但是如果你在你的应用程序中创建这个 WHERE 条件(1=1 似乎表明了这一点)你最好在那里应用你的逻辑。

【讨论】:

  • 当我在mp.chnl_name 上输入谷歌时这是否有效?我只需要 Facebook 的附加过滤器。类似下面的东西,但它不起作用。 HAVING (CASE WHEN mp.chnl_name = 'CA_FACEBOOK' AND ((GP)*100) &gt;= 7 THEN 1 ELSE 0 END) = 1 AND(CASE WHEN mp.chnl_name = 'CA_FACEBOOK' AND fsk.first_cost &gt; 500 THEN 1 ELSE 0 END) = 1
  • 您的解释完全令人困惑。为什么要使用 HAVING?
  • 我只需要mp.chnl_name = 'CA_FACEBOOK'这个过滤器。如果您查看我的 'WHERE 1=1 AND mp.chnl_name LIKE '%google%' ---------- 这是一个提示,但我硬编码测试'`这可以更改为任何其他术语。现在它只给我mp.chnl_name = 'CA_FACEBOOK' 它没有给我任何其他东西。是否有意义?如果没有,我可以想出一个清晰的主意。非常感谢
【解决方案3】:

根据您的 cmets,原来的 ELSE 条件应该是 ANDed:

SELECT 
    mp.chnl_name AS mp_channel,
    fsk.sku_prod_id AS pro_id,
    fsk.dateint  AS avlbl_dt,
    fsk.sku_num AS sku,
    fsk.upc_txt AS UPC,
    Coalesce(fsk.brand_name,'N/A') AS brand,
    fsk.ruckload AS LTL_Flag,
    fsk.price_amt AS item_selling_price,
    fsk.on_hand_unit_qty AS qoh,
    fsk.netpropt AS profite,
    (fsk.price_amt  + fsk.shpg_amt) AS lms,
    (GP)*100 AS net_pct
FROM EDW.ITEM_AVLBL mp
JOIN EDW.FULL_SKU fsk ON mp.item_id = fsk.item_id
JOIN  EDW.SHORT_SKU ssk ON ssk.sh_sku_id = fsk.sh_sku_id
WHERE 1=1
    AND (mp.chnl_name  LIKE '%google%'  ---------- This is the prompt value
    AND fsk.item_create_dt >=  '2019-10-20'
    AND  net_pct >= 10
    AND (mp.chnl_name  <> 'CA_FACEBOOK' -- if not Facebook, don't care ORed terms
         OR (GP*100  >= 7 AND fsk.first_cost > 500))
GROUP BY 1,2,3,4,5,6,7,8,9,10,11 /* ,fsk.first_cost */

我认为您不想按 first_cost 分组。这隐含地假设 mp.chnl_name 不为 NULL,因此它要么等于 CA_FACEBOOK,要么不等于。如果允许 NULL,您还需要明确检查该条件,例如(mp.chnl_name &lt;&gt; 'CA_FACEBOOK' OR mp.chnl_name IS NULL).

【讨论】:

    【解决方案4】:

    不要使用CASE:

    ( (mp.chnl_name = 'CA_FACEBOOK'  AND  ((GP)*100)  >= 7) OR
      (mp.chnl_name <> 'CA_FACEBOOK' AND fsk.first_cost > 500)
    )
    

    问题在于 Teradata 不支持从 CASE 表达式返回布尔类型。因此,您在 THEN 子句中的比较无法从语法上理解。

    编辑:

    根据您的评论,您想要的逻辑是:

    ( (mp.chnl_name = 'CA_FACEBOOK'  AND  ((GP)*100)  >= 7 AND fsk.first_cost > 500
      ) OR
      (mp.chnl_name <> 'CA_FACEBOOK' )
    )
    

    【讨论】:

    • 你错过了)
    • @Gordon Linoff 我只有在它等于 Facebook 时才需要这个条件。这就是为什么它处于案例状态。这是否按我想要的方式工作。通常,他们会插入谷歌、推特而不是 Facebook。如果是 google 或 twitter 案例条件应该影响我的报告。有意义吗?
    • 伙计们,((GP)*100) >= 7) 和 fsk.first_cost > 500 应该只在它等于 Facebook 时才有效,我需要这两个条件。当 mp.chnl_name 等于其他内容(Google 或 Twitter)时,它不应该影响我的报告。是否有意义?以上两个答案对我不起作用。
    • @WeldaSudha 。 . .这不是您的 case 表达式想要做的。它正在为 Facebook 测试 GP,而不是 Facebook 时正在测试 first_cost
    • @GordonLinoff ,对不起,如果我让你感到困惑。我要做的就是当有人键入或过滤 facebook 时,我需要 GP 应该大于 7 并且 first_cost 应该大于 500 。这应该只影响使用 Facebook 时。任何其他过滤器(搜索词如 google 或 twitter)不应影响此条件。知道如何存档吗?
    【解决方案5】:

    这对我有用,但我可能在描述中混淆了你们。非常感谢您的快速回复。我非常感谢您的帮助和时间。

    AND (CASE WHEN mp.sls_trans_web_orgn_chnl_name  = 'CA_FACEBOOK'  AND   fsk.full_sku_unit_first_cost  <  500 AND  (juice/NullIfZero(gms))*100  >= 7 THEN 1 
      WHEN mp.sls_trans_web_orgn_chnl_name  <> 'CA_FACEBOOK'  THEN 1 ELSE 0 END ) = 1  
    

    【讨论】:

    • 这是错误的 --- first_cost > 0 和 chnl_name 不是 facebook 的情况 --- 这些将被过滤掉。
    • @Hogan 我编辑了答案以在我有 0 时修复错误。但它看起来不太好。有没有其他专业的方法可以得到这个?我想更改长case语句。谢谢
    • 是的——我更新了我的答案来解决你的问题——你不需要大小写,而是使用 OR——查看我的答案中编辑后的新部分
    • @Hogan 非常感谢您的帮助和善意。老实说,这花了我两天时间。我真的很感谢你的帮助。你太棒了!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    相关资源
    最近更新 更多