【问题标题】:Finding who called who找谁打电话给谁
【发布时间】:2022-01-25 10:37:48
【问题描述】:

我有这两张桌子。订阅者表包含订阅者 ID 和他的电话号码。 NetworkP2P 内容 SubscriberID,他呼叫的 AddresseeNumber 以及呼叫开始时间和结束时间。

TABLE Subscriber 
(
    SubscriberID int,
    PhoneNumber char(10)
)

TABLE NetworkP2P 
(
    SubscriberID int,
    AddresseeNumber char(10),
    CallStart datetime,
    CallEnd datetime
)

示例数据:

订阅者

SubscriberID | PhoneNumber
1              613-555-0156
2              613-555-0112
3              613-555-0119
4              613-555-0182

网络P2P

SubscriberID | AddresseeNumber | CallStart               | CallEnd
1              613-555-0182      2013-02-03 08:27:00.000   2013-02-03 08:30:54.000
1              613-555-0119      2013-02-03 10:11:26.000   2013-02-03 10:14:26.000
1              613-555-3333      2013-02-03 15:13:58.000   2013-02-03 15:18:13.000
2              613-555-0156      2013-02-05 23:21:50.000   2013-02-05 23:24:50.000
2              613-555-0119      2013-04-05 23:21:50.000   2013-04-05 23:26:50.000
3              613-555-0112      2013-06-05 23:21:50.000   2013-06-05 23:26:50.000

并非所有电话号码都与订阅者拥有的电话号码匹配。

如果我希望输出在给定月份内相互联系的订阅者,即订阅者 1 调用订阅者 2,反之亦然,我将如何处理?

所需输出的示例:

 Caller | Reciever | CallerPhone | RecieverPhone
 1        4          613-555-0156  613-555-0182
 1        3          613-555-0156  613-555-0119
 2        1          613-555-0112  613-555-0156
 2        3          613-555-0112  613-555-0119
 3        2          613-555-0119  613-555-0112

【问题讨论】:

  • 看起来你想要加入。你试过什么?究竟是什么问题?
  • 这看起来是一个有缺陷的模型,您肯定会使用 callerID 和 receiverID 记录信息 - 该号码不应该是加入条件 - 当有人更改他们的号码时会发生什么?
  • 努力改进我提供的信息。我知道数据模型很奇怪,它没有投入生产,在创建时已经存在错误,我只是想教育自己。

标签: sql sql-server tsql


【解决方案1】:

您的模型并没有像 cmets 中所建议的那样出错 - 您的 NetworkP2P 可能仅缺少一列(接收者),该列可以用作可选外键(以满足您的句子“并非所有电话号码都与订阅者拥有的电话号码匹配”。 ),但它看起来比关系表更多。

查询您想要的输出:

select
    caller.SubscriberID as Caller,
    reciever.SubscriberID as Reciever,
    caller.PhoneNumber as CallerPhone,
    nt.AddresseeNumber as RecieverPhone, -- better than reciever.PhoneNumber because you can use left join recievers to get missing substribers
    nt.CallStart,
    nt.CallEnd
from Subscriber as caller
inner join NetworkP2P as nt
    on nt.SubscriberID = caller.SubscriberID
inner join Subscriber as reciever
    on nt.AddresseeNumber = reciever.PhoneNumber
-- where '2021-02-03' between nt.CallStart and nt.CallEnd -- calls in 2021-02-03
-- where nt.CallStart between '2021-02-01' and '2021-02-28' -- calls in specific interval
-- where eomonth(nt.CallStart) = eomonth('2021-02-01') -- calls in specific month

您应该始终为所有表使用数据库架构(例如 dbo.Subscriber)。

【讨论】:

    【解决方案2】:

    两次加入订阅者应该可以做到这一点。

    SELECT 
      nw.SubscriberID AS Caller
    , rcvr.SubscriberID AS Receiver
    , callr.PhoneNumber AS CallerPhone
    , nw.AddresseeNumber AS ReceiverPhone
    FROM NetworkP2P nw
    JOIN Subscriber callr ON callr.SubscriberID = nw.SubscriberID
    LEFT JOIN Subscriber rcvr ON rcvr.PhoneNumber = nw.AddresseeNumber
    WHERE rcvr.SubscriberID IS NOT NULL
    ORDER BY Caller, Receiver
    
    Caller Receiver CallerPhone ReceiverPhone
    1 3 613-555-0156 613-555-0119
    1 4 613-555-0156 613-555-0182
    2 1 613-555-0112 613-555-0156
    2 3 613-555-0112 613-555-0119
    3 2 613-555-0119 613-555-0112

    dbfiddle here

    上的演示

    【讨论】:

      猜你喜欢
      • 2022-01-24
      • 1970-01-01
      • 2018-05-27
      • 2017-03-22
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      • 2014-02-06
      相关资源
      最近更新 更多