【问题标题】:Atleast one and atleast not one至少一个,至少没有一个
【发布时间】:2022-01-13 08:05:40
【问题描述】:

要求:

对于策略:至少一件商品 (RAP03.propid) 有折扣 (rap14.covid = 'SS') 并且至少一件商品没有折扣 (SS)。假设我们有一个策略 (rap01.plcy) ,并且使用这个策略我们有 2 个项目 (rap03.propid)。因此,一件物品 SS 应该在那里,一件物品 SS 不应该在那里。我在下面尝试过,但记录为零。有什么办法可以同时检查这两种情况。

我们还必须尊重政策和项目 (PROPID)。一个 propid 必须包含 SS,但另一个 propid 不得包含 SS。

要求的结果:

PLCY, PROPID, COVID
000000967428613 010 SS
000000967428613 011 BB
AND EXISTS
  (SELECT 1
    /*+ use_hash(RAP03 rap14) */
  FROM rap03
JOIN rap14
ON  rap14.j31_pt_line_cat_cd = rap01.j01_PT_LINE_CAT_CD 
AND rap14.j31_pt_cdb_part_id = rap01.j01_PT_CDB_PART_ID
AND rap14.j31_pt_state_cd    = rap01.j01_PT_STATE_CD
AND rap14.plcy               = RAP01.plcy
AND rap14.propid             = RAP03.propid
AND trim(rap14.covid)        = 'SS'
AND tt.JA2_EFFDT_T BETWEEN rap14.enddt_t AND (rap14.dropdt_t - 1)
--
  WHERE RAP03.J12_PT_LINE_CAT_CD = RAP01.J01_PT_LINE_CAT_CD
  AND RAP03.J12_PT_CDB_PART_ID   = RAP01.J01_PT_CDB_PART_ID
  AND RAP03.J12_PT_STATE_CD      = RAP01.J01_PT_STATE_CD
  AND RAP03.PLCY                 = RAP01.PLCY
  AND tt.JA2_EFFDT_T BETWEEN rap03.adddt_t AND (rap03.dropdt_t  - 1)
  ) 
--
AND NOT EXISTS
  (SELECT 1
    /*+ use_hash(RAP03 rap14) */
  FROM rap03
JOIN rap14
ON  rap14.j31_pt_line_cat_cd = rap01.j01_PT_LINE_CAT_CD 
AND rap14.j31_pt_cdb_part_id = rap01.j01_PT_CDB_PART_ID
AND rap14.j31_pt_state_cd    = rap01.j01_PT_STATE_CD
AND rap14.plcy               = RAP01.plcy
AND rap14.propid             = RAP03.propid
AND trim(rap14.covid)        = 'SS'
AND tt.JA2_EFFDT_T BETWEEN rap14.enddt_t AND (rap14.dropdt_t - 1)
--
  WHERE RAP03.J12_PT_LINE_CAT_CD = RAP01.J01_PT_LINE_CAT_CD
  AND RAP03.J12_PT_CDB_PART_ID   = RAP01.J01_PT_CDB_PART_ID
  AND RAP03.J12_PT_STATE_CD      = RAP01.J01_PT_STATE_CD
  AND RAP03.PLCY                 = RAP01.PLCY
  AND tt.JA2_EFFDT_T BETWEEN rap03.adddt_t AND (rap03.dropdt_t  - 1)
  ) 

【问题讨论】:

  • edit 提出minimal reproducible example 的问题,包括:CREATE TABLE 表的声明;一些样本数据的INSERT 语句;您正在使用的我们可以运行的查询的完整(和最小)示例;问题的英文(非代码)解释;您的代码的问题/错误;以及该样本数据的预期输出。

标签: sql oracle


【解决方案1】:

您当前有WHERE EXISTS(query) AND NOT EXISTS(query),并且两个查询是相同的;这总是错误的。

认为你想要的逻辑是WHERE (at least one record exists with 'SS') AND (at least one record exists that's not 'SS')

AND EXISTS
  (SELECT 1
    /*+ use_hash(RAP03 rap14) */
  FROM rap03
JOIN rap14
ON  rap14.j31_pt_line_cat_cd = rap01.j01_PT_LINE_CAT_CD 
AND rap14.j31_pt_cdb_part_id = rap01.j01_PT_CDB_PART_ID
AND rap14.j31_pt_state_cd    = rap01.j01_PT_STATE_CD
AND rap14.plcy               = RAP01.plcy
AND rap14.propid             = RAP03.propid
AND trim(rap14.covid)        = 'SS'
AND tt.JA2_EFFDT_T BETWEEN rap14.enddt_t AND (rap14.dropdt_t - 1)
--
  WHERE RAP03.J12_PT_LINE_CAT_CD = RAP01.J01_PT_LINE_CAT_CD
  AND RAP03.J12_PT_CDB_PART_ID   = RAP01.J01_PT_CDB_PART_ID
  AND RAP03.J12_PT_STATE_CD      = RAP01.J01_PT_STATE_CD
  AND RAP03.PLCY                 = RAP01.PLCY
  AND tt.JA2_EFFDT_T BETWEEN rap03.adddt_t AND (rap03.dropdt_t  - 1)
  ) 
--

AND EXISTS -- CHANGE HERE (NOT removed)

  (SELECT 1
    /*+ use_hash(RAP03 rap14) */
  FROM rap03
JOIN rap14
ON  rap14.j31_pt_line_cat_cd = rap01.j01_PT_LINE_CAT_CD 
AND rap14.j31_pt_cdb_part_id = rap01.j01_PT_CDB_PART_ID
AND rap14.j31_pt_state_cd    = rap01.j01_PT_STATE_CD
AND rap14.plcy               = RAP01.plcy
AND rap14.propid             = RAP03.propid

AND trim(rap14.covid)       <> 'SS'  -- CHANGE HERE (= becomes <>)

AND tt.JA2_EFFDT_T BETWEEN rap14.enddt_t AND (rap14.dropdt_t - 1)
--
  WHERE RAP03.J12_PT_LINE_CAT_CD = RAP01.J01_PT_LINE_CAT_CD
  AND RAP03.J12_PT_CDB_PART_ID   = RAP01.J01_PT_CDB_PART_ID
  AND RAP03.J12_PT_STATE_CD      = RAP01.J01_PT_STATE_CD
  AND RAP03.PLCY                 = RAP01.PLCY
  AND tt.JA2_EFFDT_T BETWEEN rap03.adddt_t AND (rap03.dropdt_t  - 1)
  )

将它们结合起来可以减少代码,但实际上可能会更慢,因为它不能在找到的第一条记录处“停止”...

AND EXISTS
(
  SELECT 1
    /*+ use_hash(RAP03 rap14) */
  FROM rap03
  JOIN rap14
    ON  rap14.j31_pt_line_cat_cd = rap01.j01_PT_LINE_CAT_CD 
    AND rap14.j31_pt_cdb_part_id = rap01.j01_PT_CDB_PART_ID
    AND rap14.j31_pt_state_cd    = rap01.j01_PT_STATE_CD
    AND rap14.plcy               = RAP01.plcy
    AND rap14.propid             = RAP03.propid
    AND tt.JA2_EFFDT_T BETWEEN rap14.enddt_t AND (rap14.dropdt_t - 1)
--
  WHERE RAP03.J12_PT_LINE_CAT_CD = RAP01.J01_PT_LINE_CAT_CD
    AND RAP03.J12_PT_CDB_PART_ID   = RAP01.J01_PT_CDB_PART_ID
    AND RAP03.J12_PT_STATE_CD      = RAP01.J01_PT_STATE_CD
    AND RAP03.PLCY                 = RAP01.PLCY
    AND tt.JA2_EFFDT_T BETWEEN rap03.adddt_t AND (rap03.dropdt_t  - 1)
  HAVING
    MAX(CASE WHEN TRIM(rap14.covid) = 'SS' THEN 1 ELSE 0 END) = 1
    AND
    MIN(CASE WHEN TRIM(rap14.covid) = 'SS' THEN 1 ELSE 0 END) = 0
)

可能有更好的方法来制定查询,但我们需要更多上下文(表定义、完整查询、完整逻辑解释等)。

【讨论】:

  • WHERE (至少有一条记录存在 'SS') AND (至少有一条记录不是 'SS') ,这在某种程度上是正确的。但有更多的扭曲。假设我们有一个策略 (rap01.plcy) ,并且使用这个策略我们有 2 个项目 (rap03.propid)。因此,一件物品 SS 应该在那里,一件物品 SS 不应该在那里。
  • @KaushalTalniya - 你现在似乎在问一个不同的问题。请开始一个新问题,但包括示例数据以演示您需要的场景和逻辑。可以在此处找到有关如何编写此类问题的一些有用建议:meta.stackoverflow.com/questions/333952/…stackoverflow.com/help/minimal-reproducible-example
  • 用期望的结果编辑了问题。
  • @kaushaltalniya 您需要包括源数据以及预期结果。您将从将问题简化为可以从中学习的更简单示例中受益。 (请阅读我为您提供的两个链接,关于最小示例和可重现示例。)您应该提出新问题,而不是对现有问题进行实质性更改。
猜你喜欢
  • 2014-05-15
  • 2012-03-26
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2018-01-02
  • 2011-07-21
  • 2012-04-14
相关资源
最近更新 更多