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:
for trans_id 10 = 450(前 30 秒为 100 + 其余 5 * 70)
对于trans_id13=88
2) 客户 Samuel Gatsby 有 1 个来电和 3 个去电,但是只有 trans_id 8 和 11 是 7 月份的。他应该总共支付722:
对于 trans_id 8 = 345(前 30 秒为 100 + 其余 5 * 49)
对于trans_id11=377
仅考虑这两个示例,输出将是:
+----+----------------+------------+------------+
| 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 在线测试。
我正在尝试在两个不同的 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:
for trans_id 10 = 450(前 30 秒为 100 + 其余 5 * 70)
对于trans_id13=88
2) 客户 Samuel Gatsby 有 1 个来电和 3 个去电,但是只有 trans_id 8 和 11 是 7 月份的。他应该总共支付722:
对于 trans_id 8 = 345(前 30 秒为 100 + 其余 5 * 49)
对于trans_id11=377
仅考虑这两个示例,输出将是:
+----+----------------+------------+------------+
| 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 在线测试。