【问题标题】:Who was called?谁被叫了?
【发布时间】:2021-08-31 14:50:42
【问题描述】:

我有包含人员姓名、通话日期、from_number 和 to_number 的移动数据。 我需要关联被调用的人的姓名。

也就是说,如果我让 Barbara 从号码 x 呼叫号码 y,那么我想知道 y 或 to_number 属于谁?

下面是一个示例数据集:

SELECT  'Barbara'   AS Person,  '2020-07-03'    AS Date,'022445544' AS From_Number, '022445545' AS To_Number UNION
SELECT  'Barbara'   AS Person,  '2020-07-03'    AS Date,'091234123' AS From_Number, '022445545' AS To_Number UNION
SELECT  'Peter' AS Person,  '2020-07-03'    AS Date,    '03123456'  AS From_Number, '08007543'  AS To_Number    UNION
SELECT  'Peter' AS Person,  '2020-07-03'    AS Date,    '03123456'  AS From_Number, '022445555' AS To_Number    UNION
SELECT  'Peter' AS Person,  '2020-07-04'    AS Date,    '022445545' AS From_Number, '091234123' AS To_Number    UNION
SELECT  'Peter' AS Person,  '2020-07-04'    AS Date,    '022445545' AS From_Number, '022445555' AS To_Number    UNION
SELECT  'Peter' AS Person,  '2020-07-04'    AS Date,    '022445545' AS From_Number, '049876543' AS To_Number    UNION
SELECT  'David' AS Person,  '2020-07-03'    AS Date,    '049876543' AS From_Number, '022445544' AS To_Number    UNION
SELECT  'David' AS Person,  '2020-07-04'    AS Date,    '022445555' AS From_Number, '022445545' AS To_Number   

我试过这个:

select * 
   ,case when [From_Number] =[To_Number] then [Person] end as [from person]
   from [dbo].[cellphone] 

但我认为问题在于我不知道,你会如何表达 SQL 需要在每个人的一个人中查找所有可能的号码,因为例如 Barbara 有许多不同的电话号码。因此,就好像我会寻找一系列数字来确定来电者号码?有时,当然我们没有任何关联,因为我们不知道这个数字。然后需要将其标记为未知数字。

所需的数据集结果应如下所示:

SELECT  'Barbara'   AS Person,  '2020-07-03'    AS Date,'022445544' AS From_Number, '022445545' AS To_Number,'Peter'  AS person_called UNION
SELECT  'Barbara'   AS Person,  '2020-07-03'    AS Date,'091234123' AS From_Number, '022445545' AS To_Number, 'Peter'    AS person_called UNION
SELECT  'Peter' AS Person,  '2020-07-03'    AS Date,    '03123456'  AS From_Number, '08007543'  AS To_Number, 'unkn'     AS person_called UNION
SELECT  'Peter' AS Person,  '2020-07-03'    AS Date,    '03123456'  AS From_Number, '022445555' AS To_Number,   'David'  AS person_called UNION
SELECT  'Peter' AS Person,  '2020-07-04'    AS Date,    '022445545' AS From_Number, '091234123' AS To_Number,   'Barbara'AS person_called UNION
SELECT  'Peter' AS Person,  '2020-07-04'    AS Date,    '022445545' AS From_Number, '022445555' AS To_Number,   'David'  AS person_called UNION
SELECT  'Peter' AS Person,  '2020-07-04'    AS Date,    '022445545' AS From_Number, '049876543' AS To_Number,   'David'  AS person_called UNION
SELECT  'David' AS Person,  '2020-07-03'    AS Date,    '049876543' AS From_Number, '022445544' AS To_Number,   'Barbara'AS person_called UNION
SELECT  'David' AS Person,  '2020-07-04'    AS Date,    '022445555' AS From_Number, '022445545' AS To_Number ,  'Peter'  AS person_called 


I also tried this : 



   SELECT A.Person, A.Date, A.From_Number, A.To_Number      
    ,CASE WHEN EXISTS (SELECT B.Person, B.Date, B.From_Number, B.To_Number FROM [dbo].[mobile_data] B 
                        WHERE B.From_Number = A.To_Number)
    THEN B.Person = A.Person    ELSE 'Unknown'   END as caller_id
   from [dbo].[mobile_data] a

但我收到以下错误消息:The multi-part identifier "B.Person" could not be bound. 基本上我需要:THEN B.Person ELSE 但即使我尝试这个它说 B.Person 不能被绑定。 语法错误在哪里?

【问题讨论】:

  • 请根据所提供的样本数据显示您想要的结果。
  • 创建一个临时表。 SELECT A.Person, CASE WHEN EXISTS (SELECT * FROM table2 B WHERE B.From_Number = A.To_Number) THEN (SELECT From_Number FROM table2 B WHERE B.From_Number = A.To_Number) ELSE 'Unknown' END FROM table1 A 没有测试,但是如果我理解正确,您需要通过创建子查询并使用 case 语句来检查数字是否存在,然后在肯定的情况下抓取它或返回 Unknown 作为字符串.当然,您需要添加更多内容。
  • 您是否知道您所拥有的信息不足以在所有情况下回答该问题?使用您拥有的数据,如果该人在某个时间点也拨打了电话,您只能获取与呼叫接收者号码相关联的姓名。
  • 好的,只是确保。作为开始的提示,请记住您可以将表连接到自身。因此,如果您的表名为calls,您可以执行select ... from calls as callers join calls as recipients on ...,并填写该联接的逻辑(提示,您将加入两个电话号码列)。这能让你开始吗?
  • 这是一个很好的尝试。您应该更新您的问题以将该尝试包含为格式化代码和错误消息,而不是将其作为注释。此外,鉴于您的更新包含“未知数”,请将我的“提示”评论阅读为 left join 而不是 join(但也可以按照您的方式完成)

标签: sql sql-server tsql


【解决方案1】:

让我更改您的查询格式,以便在有用的位置添加 cmets。

  select A.Person, 
         A.Date, 
         A.From_Number, 
         A.To_Number,
         case
            when exists 
            (
               select   B.Person, B.Date, B.From_Number, B.To_Number 
               from     [dbo].[mobile_data] B 
               where    B.From_Number = A.To_Number
               -- the bit after "then" must  be the value you want if the "when" condition is true.
               -- the expression "b.person = a.person" isn't a value, it's either a check whether two things are equal,
               -- or an assignment from the thing on the right hand side to the thing on the left hand side
            ) then B.Person = A.Person 
            else 'Unknown'  
          end as caller_id
   -- This "from" clause only includes the alias "a". There's no "b" alias here. 
   -- So you can't refer to anything from "b" in this outer select.
   -- "b" only lives inside the "exists" condition above, it can't be seen from out here
   -- but you referred to b outside the "exists" condition, in the "then B.Person = A.Person ". 
   -- That's why SQL is saying that the "b.person" identifier could not be bound (it can't see it out here).
   from [dbo].[mobile_data] a

为了以我认为你想要的方式回答你的问题,我们必须做出一个断言:一个人可以有多个电话号码,但一个电话号码只能属于一个人。

如果这是正确的,我们可以接听这些电话并将它们重新连接到自己以获得答案。我们将获取呼叫者to_number,并尝试将其与其他人的from_number 匹配。如果我们没有匹配到,那么被呼叫的人自己没有拨打任何电话,所以我们不知道他们是谁。

我们也必须使用distinct,因为一个人可以拨打多个电话。例如,芭芭拉拨打了属于彼得的号码 022445544。但是彼得已经打了 4 个电话,所以我们会将芭芭拉的电话与彼得打的所有电话相匹配。但是,当然,在所有 4 次调用中,都是由 Peter 完成的,所以如果我们使用 distinct,我们只会得到一个 Peter,这就是我们想要的。

create table calls 
(
   from_name varchar(32),
   call_date date,
   from_number varchar(16),
   to_number varchar(16)
);

insert   calls
values   ('Barbara', '2020-07-03','022445544',  '022445545'),
         ('Barbara', '2020-07-03','091234123',  '022445545'),
         ('Peter',   '2020-07-03','03123456',   '08007543'),
         ('Peter',   '2020-07-03','03123456',   '022445555'),
         ('Peter',   '2020-07-04','022445545',  '091234123'),
         ('Peter',   '2020-07-04','022445545',  '022445555'),
         ('Peter',   '2020-07-04','022445545',  '049876543'),
         ('David',   '2020-07-03','049876543',  '022445544'),
         ('David',   '2020-07-04','022445555',  '022445545');

select      distinct
            callers.*,
            to_name = isnull(recipients.from_name, 'unkn')
from        calls    callers
left join   calls    recipients on recipients.from_number = callers.to_number;            

【讨论】:

    【解决方案2】:

    我使用了在线 REPL 并先设置了表格。

    CREATE TABLE people
    ( Person VARCHAR NOT NULL,
      Date VARCHAR NOT NULL,
      From_Number VARCHAR NOT NULL,
      To_Number VARCHAR NOT NULL
    );
    insert into people values('Barbara','2020-07-03','022445544','022445545');
    insert into people values('Barbara','2020-07-03','091234123','022445545');
    insert into people values('Peter','2020-07-03','03123456','08007543');
    insert into people values('Peter','2020-07-03','03123456','022445555');
    insert into people values('Peter','2020-07-04','022445545','091234123');
    insert into people values('Peter','2020-07-04','022445545','022445555');
    insert into people values('Peter','2020-07-04','022445545','049876543');
    insert into people values('David','2020-07-03','049876543','022445544');
    insert into people values('David','2020-07-04','022445555','022445545');
    

    然后,使用以下查询。

    SELECT *,
        CASE WHEN EXISTS (SELECT * FROM people B WHERE B.From_Number = A.To_Number)
            THEN (SELECT Person FROM people B WHERE B.From_Number = A.To_Number)
            ELSE 'Unknown'
        END Person_Called
    FROM people A
    

    这给了我以下结果。

    Barbara|2020-07-03|022445544|022445545|Peter
    Barbara|2020-07-03|091234123|022445545|Peter
    Peter|2020-07-03|03123456|08007543|Unknown
    Peter|2020-07-03|03123456|022445555|David
    Peter|2020-07-04|022445545|091234123|Barbara
    Peter|2020-07-04|022445545|022445555|David
    Peter|2020-07-04|022445545|049876543|David
    David|2020-07-03|049876543|022445544|Barbara
    David|2020-07-04|022445555|022445545|Peter
    

    【讨论】:

    • 嗨@DanielCazares,谢谢你的提示。它不适用于主查询,因为有些人最多有 3 个电话号码。我确实认为添加一个 ID(如: ADD ID INT IDENTITY(1,1) )可以解决这个问题。但我无法在我的观点中实现这一点。不确定你可以。但仍然是有效的输入!
    【解决方案3】:
    WITH
    cellphone
    AS
    (
       SELECT tbl.* FROM (VALUES
        ( 'Barbara', '03-Jul-2020', '022445544', '022445545')
       , ( 'Barbara', '03-Jul-2020', '091234123', '022445545')
       , ( 'David', '03-Jul-2020', '049876543', '022445544')
       , ( 'David', '04-Jul-2020', '022445555', '022445545')
       , ( 'Peter', '03-Jul-2020', '03123456', '022445555')
       , ( 'Peter', '03-Jul-2020', '03123456', '08007543')
       , ( 'Peter', '04-Jul-2020', '022445545', '022445555')
       , ( 'Peter', '04-Jul-2020', '022445545', '049876543')
       , ( 'Peter', '04-Jul-2020', '022445545', '091234123')
       ) tbl ([Person], [Date], [From_Number], [To_Number]) 
    )
    , 
    person_cellphone
    AS
    (
       SELECT DISTINCT 
            [Person]
          , [From_Number]
       FROM 
          cellphone
    )
    SELECT 
         cel.[Person]
        , cel.[Date]
        , cel.[From_Number]
        , cel.[To_Number]
        , [To_Number] = ISNULL(pct.[Person], '<N/A>')
    FROM 
       cellphone AS cel
       LEFT JOIN person_cellphone AS pct ON pct.[From_Number] = cel.[To_Number]
    

    【讨论】:

      猜你喜欢
      • 2012-09-15
      • 2014-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      相关资源
      最近更新 更多