【问题标题】:Select Records With Only One Value In A Column Where Multiple Are Possible在可能有多个值的列中选择只有一个值的记录
【发布时间】:2014-03-09 15:42:57
【问题描述】:

我提前道歉,这可能是一个基本问题,但我不知道如何用词搜索以找到正确的结果。

我有一个表(在其他列中)包含客户编号的程序名称。我需要确定只有一个特定程序而没有其他程序的客户。一个简化的例子:

Col1 = Customer_Number,Col2 = Program_Name

客户 1 有 3 条记录,因为他们注册了 2013BA1111、2013BO1161 和 2013BO1163。客户 2 只有一条记录,因为他们只注册了 2013BA1111。

使用 Teradata SQL 助手,如果我选择 WHERE Program_Name = '2013BA1111',则客户 1 和客户 2 都将返回,因为他们都注册了计划 2013BA1111。我只想选择客户 2,因为他们只有 2013BA1111。

谢谢!

【问题讨论】:

    标签: sql teradata


    【解决方案1】:

    大概是这样的:

    select Customer_Number, Program_Name
    from YourTable t1
    left join (
        select Customer_Number
        from YourTable t2
        where t2.Program_Name <> '2013BA1111'
    ) t3 on t1.Customer_Number = t3.Customer_Number
    where 
    t1.Program_Name = '2013BA1111'
    and t3.Customer_Number is null
    

    外部查询选择具有给定Program_Name 的所有记录,然后与具有不等于给定Program_Name 记录的每个人的内部查询连接,外部查询检查以确保连接的内部查询没有匹配项。

    【讨论】:

    • 我认为 '2013BA1111' 只是一个例子
    • 正确。这是 OP 在他的帖子中使用的那个。
    • 是的,但我的意思是 user3298276 不想获取特定的行。任何只出现一次的行都是我认为的要求
    • 通过 OP 声明“我需要确定只有一个特定程序而没有其他程序的客户”,我假设他们有一个特定的程序要搜索。我可能误会了。
    • 正确,在这种情况下,我只想用“2013BA1111”识别客户。它是所有客户都应该拥有的基本程序,但我认为将来能够用任何程序名称替换它是有用的。感谢您到目前为止的帮助,我将在今天下午返回我的查询并尝试其中一些。
    【解决方案2】:

    这将在 SQL Server 中完成。不确定 Teradata 是否相同...

    select t.Col1, min(t.Col2) from myTable t
    group by t.Col1
    having count(*) = 1
    

    【讨论】:

    • 这有效,但仅适用于 2013BA1111,因为所有客户都有此程序。如果我担心另一个程序,它可能不会 - 但这也满足了我的迫切需求......谢谢!
    【解决方案3】:

    我不熟悉“Teradata”,但你应该可以在 sql 中使用类似的东西:

    SELECT 
         Col1 AS Customer,
         COUNT(*) AS TotalOccurences
    FROM
         YourTable
    GROUP BY Col1
    HAVING COUNT(*) = 1
    

    【讨论】:

    • 这有效,但仅适用于 2013BA1111,因为所有客户都有此程序。如果我担心另一个程序,它可能不会 - 但这也满足了我的迫切需求......谢谢!
    【解决方案4】:

    在标准 (ANSI/ISO) SQL 中,派生表 是您的朋友。在这里,我们将客户表与一个派生表连接起来,该派生表生成只有 1 个客户的列表

    select *
    from customer c
    join ( select customer_id
           from customer
           group by customer_id
           having count(program_name) = 1
         ) t on t.customer_id = c.customer_id
    where ... -- any further winnowing of the result set occurs here
    

    【讨论】:

      【解决方案5】:

      您只需要 customer_number 或其他列吗?

      SELECT Customer_Number
      FROM tab
      GROUP BY 1
      HAVING SUM(CASE WHEN Program_Name = '2013BA1111' THEN 0 ELSE 1 END) = 1;
      
      SELECT *
      FROM tab AS t1
      WHERE Program_Name = '2013BA1111' 
      AND NOT EXISTS
       (
         SELECT * FROM tab AS t2 
         WHERE t1.Customer_Number = t2.Customer_Number
           AND Program_Name <> '2013BA1111'
       );
      
      SELECT *
      FROM tab
      QUALIFY
         SUM(CASE WHEN Program_Name = '2013BA1111' THEN 0 ELSE 1 END) 
         OVER (PARTITION BY Customer_Number) = 1;
      

      【讨论】:

      • 虽然如果我有这种需要,这可能会起作用,但它有点超出我的理解范围。我可能会花一些时间来剖析它,但我认为现在一些简单的答案就足够了。谢谢!
      猜你喜欢
      • 2020-08-06
      • 2018-02-23
      • 1970-01-01
      • 1970-01-01
      • 2016-12-28
      • 2020-02-29
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      相关资源
      最近更新 更多