SQL 如何将交易数据与客户数据表连接起来并执行基于案例的操作

How to join transactional data with customer data tables and perform case-based operations in SQL

我正在尝试在两个不同的 table 之间执行查询,并根据具体情况得出一个特定月份的呼叫记录列表。

这是我的 tables:

客户table:

+----+----------------+------------+
| id |      name      |   number   |
+----+----------------+------------+
|  1 | John Doe       | 8973221232 |
|  2 | American Dad   | 7165531212 |
|  3 | Michael Clean  | 8884731234 |
|  4 | Samuel Gatsby  | 9197543321 |
|  5 | Mike Chat      | 8794029819 |
+----+----------------+------------+

交易数据:

+----------+------------+------------+----------+---------------------+
| trans_id |  incoming  |  outgoing  | duration |      date_time      |
+----------+------------+------------+----------+---------------------+
|        1 | 8973221232 | 9197543321 |       64 | 2018-03-09 01:08:09 |
|        2 | 3729920490 | 7651113929 |      276 | 2018-07-20 05:53:10 |
|        3 | 8884731234 | 8973221232 |      382 | 2018-05-02 13:12:13 |
|        4 | 8973221232 | 9234759208 |      127 | 2018-07-07 15:32:30 |
|        5 | 7165531212 | 9197543321 |      852 | 2018-08-02 07:40:23 |
|        6 | 8884731234 | 9833823023 |      774 | 2018-07-03 14:27:52 |
|        7 | 8273820928 | 2374987349 |      120 | 2018-07-06 05:27:44 |
|        8 | 8973221232 | 9197543321 |       79 | 2018-07-30 12:51:55 |
|        9 | 7165531212 | 7651113929 |      392 | 2018-05-22 02:27:38 |
|       10 | 5423541524 | 7165531212 |      100 | 2018-07-21 22:12:20 |
|       11 | 9197543321 | 2983479820 |      377 | 2018-07-20 17:46:36 |
|       12 | 8973221232 | 7651113929 |      234 | 2018-07-09 03:32:53 |
|       13 | 7165531212 | 2309483932 |       88 | 2018-07-16 16:22:21 |
|       14 | 8973221232 | 8884731234 |       90 | 2018-09-03 13:10:00 |
|       15 | 3820838290 | 2093482348 |      238 | 2018-04-12 21:59:01 |
+----------+------------+------------+----------+---------------------+

我想要完成什么?

我正在尝试为 2018 年 7 月打电话的每个客户编制一份 "costs" 的列表。费用基于:

1) 如果客户接到电话(打入),则通话费用等于时长;

2) 如果客户拨打电话(拨出),通话时长不超过 30 分钟,通话费用为 100 美元。如果超过 30 个持续时间,则成本为 100 加上 5 * 超出的持续时间。

如果客户在那个月没有打任何电话,他就不应该在名单上。

示例:

1) 客户美国爸爸有 3 个来电和 1 个去电,但是只有 trans_id 10 和 13 是 7 月份的。他一共应该付538:

2) 客户 Samuel Gatsby 有 1 个来电和 3 个去电,但是只有 trans_id 8 和 11 是 7 月份的。他应该总共支付722:

仅考虑这两个示例,输出将是:

+----+----------------+------------+------------+
| id |      name      |   number   |  billable  |
+----+----------------+------------+------------+
|  2 | American Dad   | 7165531212 |        538 |
|  4 | Samuel Gatsby  | 9197543321 |        722 |
+----+----------------+------------+------------+

注意:Mike Chat 不应在列表中,因为他在那个特定月份没有拨打或接听任何电话。

到目前为止我尝试了什么?

我一直在用这个玩猫捉老鼠的游戏,我使用数字作为唯一 ID,已经尝试了完全外部连接和合并,其中传入或传出不为空,然后按情况应用规则,尝试这样做a left join 和 application cases,但我在四处转转,​​无法获得最终列表。每当我进入或离开时,我要么无法应用案例,要么无法将两者结合在一起。非常感谢您的帮助!

select customer_name.name, customer_name.number, bill = (CASE
                                                         WHEN customer_name.number = transaction_data.incoming then 'sum bill'
                                                         else 'multiply and add'
                                                         end)
from customer_name
left join transaction_data on customer_name.number = transaction_data.incoming or customer_name.name = transaction_data.outgoing
where strftime('%Y-%m', transaction_data.date_time) = '2018-07'

注意:我正在使用 sqlite 在线试用,但数据库在 SQL Server 2012 上,所以我知道我可以更轻松地使用日期格式,但我会喜欢尽可能靠近T-SQL。

还尝试创建一个案例来确定它是来电还是去电,但结果我只收到来电,即使 trans_id 10 是去电:

select name, number, duration, case 
    when customer_name.number = transaction_data.incoming then 'incoming'
    when customer_name.number = transaction_data.outgoing then 'outgoing'
END direction
from customer_name
left join transaction_data on customer_name.number = transaction_data.incoming or customer_name.name = transaction_data.outgoing
where strftime('%Y-%m', transaction_data.date_time) = '2018-07'

试试这个:

SELECT
  c."name", c.number,
  SUM(CASE c.number
        WHEN t.incoming THEN t.duration
        ELSE IIF(t.duration - 30 < 0, 0, t.duration - 30) * 5 + 100
      END) AS billable
FROM Customer AS c INNER JOIN [Transaction] AS t
  ON c.number IN(t.incoming, t.outgoing)
WHERE t.date_time >= '20180701' AND t.date_time < '20180801'
GROUP BY c."name", c.number

输出:

|     name      |   number   | billable |
+---------------+------------+----------+
| John Doe      | 8973221232 |      440 |
| American Dad  | 7165531212 |      538 |
| Michael Clean | 8884731234 |      774 |
| Samuel Gatsby | 9197543321 |      722 |

使用 SQL Fiddle 在线测试。