【问题标题】:Testing for existence using SELECT WHERE HAVING and NOT HAVING in a grouped subset在分组子集中使用 SELECT WHERE HAVING 和 NOT HAVING 测试存在性
【发布时间】:2010-12-30 10:15:01
【问题描述】:

编辑:最后的示例 I/O。

如果存在特定条件或不存在其他条件,我需要对这些数据进行 +1 计数。我正在使用 SQL Server 2008。

我将以下简化的示例 XML 分解为临时表并对其进行验证:

  <product type="1">
    <param type="1">
      <item mode="0" weight="1" />
    </param>
    <param type="2">
      <item mode="1" weight="1" />
      <item mode="0" weight="0.1" />
    </param>
    <param type="3">
      <item mode="1" weight="0.75" />
      <item mode="1" weight="0.25" />
    </param>
  </product>

所关注的验证是以下规则:

对于每种产品类型,每种参数类型, 模式可能是 0 & (1 || 2)。在 换句话说,可能有一个 0(s),但是 然后需要 1s 或 2s,或者有 可能只有 1(s) 或 2(s)。不能有 只能是0,不能有1 和 2 秒。

我唯一没有弄清楚的部分是如何检测是否只有 0。这似乎是一个“没有”的问题。

验证码(本部分):

WITH t1 AS (
    SELECT      SUM(t.ParamWeight) AS S, COUNT(1) AS C, 
                t.ProductTypeID, t.ParamTypeID, t.Mode
    FROM        @t AS t
    GROUP BY    t.ProductTypeID, t.ParamTypeID, t.Mode
),
    ...
    UNION ALL           
    SELECT      TOP (1) 1   -- only mode 0 & (1 || 2) is allowed
    FROM        t1
    WHERE       t1.Mode IN (1, 2)
    GROUP BY    t1.ProductTypeID, t1.ParamTypeID
    HAVING      COUNT(1) > 1
    UNION ALL
    ...
)
SELECT      @C = COUNT(1)
FROM        t2

这将显示是否混合了任何模式 1 和 2,但如果组仅包含 0,则不会显示。我确信有一个简单的解决方案,但它现在正在回避我。

编辑:

我想到了一个完美的“作弊”。我在上面添加了以下内容:

SELECT      TOP (1) 1   -- only mode 0 & (null || 1 || 2) is allowed
FROM        t1
GROUP BY        t1.ProductTypeID, t1.ParamTypeID
HAVING      SUM(t1.Mode) = 0

但是,我仍然想知道如何做到这一点而不作弊。

示例

Zero  One  Two  Result
1     0    0    False
0     1    1    False
1     1    1    False
0     1    0    True
0     0    1    True
1     1    0    True
1     0    1    True

【问题讨论】:

    标签: sql sql-server group-by aggregate-functions


    【解决方案1】:

    好吧,您可以编写以下查询:

    SELECT ProductTypeID,ParamTypeID,MIN(Mode) as Has0,MAX(Mode) as M1or2,MAX(CASE WHEN Mode=1 THEN 1 ELSE 0 END) as M1
    from @t
    group by ProductTypeID,ParamTypeID
    

    我认为您可以只使用这 3 列来回答您的查询。如果Has0 = 0,则存在模式 0 值,因此您需要 M1or2 大于 0(如果我理解正确的话)。

    您还可以验证如果 M1or2 = 2,那么(我认为)您希望 M1 为 0(如果找到模式 2 行,则未找到模式 1 行)。

    我想我没看错你的描述。如果没有,添加一些“允许”和“不允许”组合的示例可能会有所帮助。


    SELECT ProductTypeID,ParamTypeID,CASE
        WHEN M1OrM2 = 2 And M1 = 1 THEN 0 /* Have both mode 2 and mode 1. Can ignore whether it has any Mode 0 */
        WHEN Has0 = 0 AND M1OrM2 = 0 THEN 0 /* Has a mode 0 and no M1 or M2 */
        ELSE 1 END /* All other combinations are allowed */
    FROM (
    SELECT ProductTypeID,ParamTypeID,MIN(Mode) as Has0,MAX(Mode) as M1or2,MAX(CASE WHEN Mode=1 THEN 1 ELSE 0 END) as M1
    from @t
    group by ProductTypeID,ParamTypeID
    ) t
    

    【讨论】:

    • 谢谢达米安。如果我正确阅读了您的 SQL,在我看来,如果 min 模式为 1,则 Has0 可能为 1。是的......我测试了它。我会按照您的建议发布一些示例。
    • @IanC - 我添加了一个新查询,其中有一列为您的示例“假”行返回 0,否则为 1。够了吗?
    • 50 次观看,只有你回答了 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 2019-12-09
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    相关资源
    最近更新 更多