【问题标题】:Checking if a value exists on a sub-query检查子查询中是否存在值
【发布时间】:2017-11-09 16:31:57
【问题描述】:

我有以下查询:

SELECT 
   c.callID,
   c.time,
   c.duration,
   (case_statement) AS inquiry_type
FROM calls AS c

我的问题是关于构建 case_statement。还有另一个表call_hcocallshco 关联在一起。

如果callIDcall_hco 表上有hco = 61,我需要case_statement,那么inquiry_type 将是“服务”。如果callID 具有hco = 52hco = 54hco = 56,则inquiry_type 将为“销售”,否则inquiry_type 将为“NULL”。

值得一提的是,如果您在call_hco 上查询特定的callID,它可以返回一行或多行,因为同一个callID 可能与多个hco 相关联。

查询结果应该类似于:

callID    time    duration(seconds)    inquiry_type
12        15:35         55                 Service
15        10:56         135                Sales
16        18:36         45                 NULL
18        13:00         234                Sales

非常感谢任何帮助。

【问题讨论】:

  • c.callID 是 call_hco 的关键吗?给我们 call_hco 的定义
  • 我希望有一个 CallType 表。然后你可以简单地在 hco 上加入它。然后,如果您需要更改它,您的查询将正常工作,您不必更改硬编码的 case 表达式。或者在您的 hco 表中添加另一列以在其中包含inquiry_type。
  • call_hco 有 call_cho_id(integer)、callID(integer)、hco(integer) 和一些不相关的列,如 ip、timeEntered 等

标签: sql-server


【解决方案1】:

值得一提的是,如果您在 call_hco 上查询特定的 callID,它可以返回一行或多行,因为同一个 callID 可能与多个 hco 相关联。

要正确回答这个问题,我们需要知道您如何决定 call_hco 记录正确。有时间戳吗? hco 字段是否是一个进步(所以最高的数字总是获胜)?您想显示该呼叫的多个结果吗?

没有这些信息,我们只是猜测。

也就是说,我猜猜你自己完成可能就足够了。尝试像使用 JOIN 一样使用 APPLY 操作,将原始表中的每条记录限制为添加表中的一条匹配记录:

SELECT 
   c.callID,
   c.time,
   c.duration,
   CASE WHEN h.hco = 61 THEN 'Service' WHEN h.hco IN (52,54,56) THEN 'Sales' ELSE NULL END AS inquiry_type
FROM calls AS c
OUTER APPLY (
        SELECT TOP 1 hco 
        FROM call_hco 
        WHERE call_hco.callID = c.callID 
            AND call_hco.callID IN (52,54,56,61)
        ORDER BY hco DESC) h

再次...这里的ORDER BY 是一个疯狂的猜测,可能不是您想要的,但您可以使用这种技术来获得您真正想要的记录。

因为您只需要call_hco 中的一个字段,您也可以在 select 子句中使用相关派生表(子查询)来执行此操作,并可能将其抽象到 CTE 以使查询更易于理解和维护。但我发现 APPLY 更易于使用,并且还可以轻松地从相关表中获取其他字段。

您可以使用可能看起来像这样的hco_type 表使这变得更好:

hco 类型 61 服务 52 销售 54 销售 56 销售

然后您可以通过加入这个新表来简化CASE 表达式:

SELECT 
   c.callID,
   c.time,
   c.duration,
   t.type
FROM calls AS c
OUTER APPLY (
        SELECT TOP 1 hco 
        FROM call_hco 
        WHERE call_hco.callID = c.callID 
            AND call_hco.callID IN (52,54,56,61)
        ORDER BY hco DESC) h
LEFT JOIN hco_type t ON t.hco = h.hco

【讨论】:

  • 没有关于采用哪个 call_hco 记录的规则。我需要检查给定的 callID 是否在此表上有记录。如果是这样,如果值是 61,那么我需要显示字符串“服务”。如果存在以下值之一 (52,54,56),则显示字符串“Sales”。如果根本没有记录或有记录但没有上面的 hco 值,则显示“NULL”。我更喜欢在查询的 select 部分使用 case 语句,并避免加入 call_hco 表,因为当我加入它时会增加返回的行数并且过滤变得更加复杂。
  • 如果您同时拥有销售和服务 hco 值怎么办?无论如何,基于此,我更新了查询,因此它可能已经完成了您需要的操作。此 APPLY 查询将从不增加返回的行数,但如果调用同时具有 Sales 和 Server hco,它可能会返回不一致或不可预测的结果。
  • 这非常适合我想要的。我真的很喜欢您添加的 call_type 表的想法,它使代码更易于阅读。谢谢。
  • @DoArNa 我还是很好奇:如果一个电话的 hco 同时为 61 和 52,你怎么知道它是 Sales 还是 Service?
  • 一个调用不能有两个值。它的工作方式是,当一个呼叫进来时,有一个流程(包括人工)为呼叫分配一个 hco 值,即 61(服务)或 52 或 54 或 56 用于销售(不同类型的销售)。可以为呼叫分配更多的 hco 值,例如 94(已预约)或 86(未预约等)。因此,呼叫可以具有多个 hco 值,例如 61 和 94,这意味着它是一个服务呼叫并留下一个约会,但是它不能有 61 并且说 52,因为这意味着它同时是一个服务和销售电话。
【解决方案2】:

这很简单,因为您已经列出了条件。唯一容易搞砸的部分是没有将ELSE null 作为最后一个条件:

SELECT 
   c.callID,
   c.time,
   c.duration,
   CASE 
     WHEN h.hco = 61 THEN 'Service'
     WHEN h.hco in (52,54,56) THEN 'Sales'
     ELSE null
    END AS inquiry_type
FROM calls AS c
inner join hco_table as h
on c.callID = h.callID

【讨论】:

  • 我更喜欢在查询的选择部分使用 case 语句,并避免加入 call_hco 表,因为当我加入它时会增加返回的行数并且过滤变得更加复杂。这可能吗?
  • 不是我能想到的。正如最佳答案所暗示的那样,有一些方法可以使连接查询为每个 ID 返回一行,但您确实需要以某种方式指定哪一行。
  • 问题是我根本不需要返回任何行。我需要比较我的给定值(例如 61)是否是子查询结果的一部分,如果它是其他值的显示“服务”等等....
  • 对,如果您指定每个callID 要检查的单个 hco 行,这就是该查询的内容。您只会得到指定的字段,其中不包括任何 hco 字段。
  • 哦,我明白你在说什么。我会试一试。谢谢!
【解决方案3】:

假设 callID 是两个表的键。如果 call_hco 有多行具有相同的 callID,那么结果中也会有多行:

SELECT 
   c.callID,
   c.time,
   c.duration,
   CAST (
       case h.hco 
         WHEN 61 THEN 'Service' 
         WHEN 52 THEN 'Sales' 
         WHEN 54 THEN 'Sales' 
         WHEN 56 THEN 'Sales' 
         ELSE NULL END AS varchar(7) 
        )
                                        AS inquiry_type
FROM calls AS c
   LEFT JOIN call_hco as h
        ON h.callID = c.callID 
           AND h.hco IN ( 61, 52, 54, 56 );

编辑:我添加了子句 AND h.hco IN (...) 以避免添加 call_hco.hco 与这些值不匹配的行。

【讨论】:

  • 我更喜欢在查询的选择部分使用 case 语句,并避免加入 call_hco 表,因为当我加入它时会增加返回的行数并且过滤变得更加复杂。这可能吗?
  • 我在连接上添加了额外的过滤器以避免在不需要的地方添加行
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 2011-06-10
  • 1970-01-01
相关资源
最近更新 更多