- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含客户信息的表。每个客户都被分配了一个客户 ID(他们的 SSN),他们在开设更多账户时会保留该 ID。两个客户可能在同一个帐户上,每个客户都有自己的 ID。帐号不按日期排序。
我想找到每个客户或客户组的最新帐户。如果两个客户曾经一起使用过一个帐户,我想返回任一客户最近使用过的帐户。
这是一个包含一些可能情况的示例表。
示例表 ACCT:
acctnumber date Cust1ID Cust2ID
10000 '2016-02-01' 1110 NULL --Case0-customer has only ever had
--one account
10001 '2016-02-01' 1111 NULL --Case1-one customer has multiple
10050 '2017-02-01' 1111 NULL --accounts
400050 '2017-06-01' 1111 NULL
10089 '2017-12-08' 1111 NULL
10008 '2016-02-01' 1120 NULL --Case2-customer has account(s) and later
10038 '2016-04-01' 1120 NULL
10058 '2017-02-03' 1120 1121 --gets account(s) with another customer
10002 '2016-02-01' 1112 NULL --Case3-customer has account(s) and later
10052 '2017-02-02' 1113 1112 --becomes the second customer on another
10152 '2017-05-02' 1113 1112 --account(s)
10003 '2016-02-02' 1114 1115 --Case4-customer and second customer
7060 '2017-02-04' 1115 1114 --switch which is first and second
10004 '2016-02-02' 1116 1117 --Case5-second customer later gets
10067 '2017-02-05' 1117 NULL --separate account(s)
10167 '2018-02-05' 1117 NULL
50013 '2016-01-01' 2008 NULL --Case5b -customer has account(s) & later
50014 '2017-02-02' 2008 2009 --gets account(s) with second customer &
50015 '2017-04-04' 2008 NULL --later still first customer gets
100015 '2018-05-05' 2008 NULL --separate account(s)
30005 '2015-02-01' 1118 NULL --Case6-customer has account(s)
10005 '2016-02-01' 1118 NULL
10054 '2017-02-02' 1118 1119 --gets account(s) with another
40055 '2017-03-03' 1118 1119
10101 '2017-04-04' 1119 NULL --who later gets separate account(s)
10201 '2017-05-05' 1119 NULL
30301 '2017-06-06' 1119 NULL
10322 '2018-01-01' 1119 NULL
10007 '2016-02-01' 1122 1123 --Case7-customers play musical chairs
10057 '2017-02-03' 1123 1124
10107 '2017-06-02' 1124 1125
50001 '2016-01-01' 2001 NULL --Case8a-customers with account(s)
50002 '2017-02-02' 2001 2002 --together each later get separate
50003 '2017-03-03' 2001 NULL --account(s)
50004 '2017-04-04' 2002 NULL
50005 '2016-01-01' 2003 NULL --Case8b-customers with account(s)
50006 '2017-02-02' 2003 2004 --together each later get separate
50007 '2017-03-03' 2004 NULL --account(s)
50008 '2017-04-04' 2003 NULL
50017 '2018-03-03' 2004 NULL
50018 '2018-04-04' 2003 NULL
50009 '2016-01-01' 2005 NULL --Case9a-customer has account(s) & later
50010 '2017-02-02' 2005 2006 --gets account(s) with a second customer
50011 '2017-03-03' 2005 2007 --& later still gets account(s) with a
--third customer
50109 '2016-01-01' 2015 NULL --Case9b starts the same as Case9a, but
50110 '2017-02-02' 2015 2016
50111 '2017-03-03' 2015 2017
50112 '2017-04-04' 2015 NULL --after all accounts with other customers
50122 '2017-05-05' 2015 NULL --are complete, the original primary
--customer begins opening individual
--accounts again
acctnumber date Cust1ID Cust2ID
10000 '2016-02-01' 1110 NULL --Case0
10089 '2017-12-08' 1111 NULL --Case1
10058 '2017-02-03' 1120 1121 --Case2
10152 '2017-05-02' 1113 1112 --Case3
7060 '2017-02-04' 1115 1114 --Case4
10167 '2018-02-05' 1117 NULL --Case5
100015 '2018-05-05' 2008 NULL --Case5b
10322 '2018-01-01' 1119 NULL --Case6
10107 '2017-06-02' 1124 1125 --Case7
50003 '2017-03-03' 2001 NULL --Case8a result 1
50004 '2017-04-04' 2002 NULL --Case8a result 2
50017 '2018-03-03' 2004 NULL --Case8b result 1
50018 '2018-04-04' 2003 NULL --Case8b result 2
50011 '2017-03-03' 2005 2007 --Case9a
50122 '2017-05-05' 2015 NULL --Case9b
10007 '2016-02-01' 1122 1123 --Case7 result 1
10107 '2017-06-02' 1124 1125 --Case7 result 2
select
max(date1) as date,
cust1id1 as cust1id
from
(
select
acctnumber as [acctnumber1],
date as [date1],
cust1id as [cust1id1],
cust2id as [cust2id1]
from
acct
) t1
join
(
select
acctnumber as [acctnumber2],
date as [date2],
cust1id as [cust1id2],
cust2id as [cust2id2]
from
acct
) t2
on t1.date1 > t2.date2 and
(t1.cust1id1 = t2.cust1id2 or
t1.cust1id1 = t2.cust2id2 or
t1.cust2id1 = t2.cust2id2)
Group by
cust1id1
union
select
max(date1) as date,
cust1id1 as cust1id
from
(
select
acctnumber as [acctnumber1],
date as [date1],
cust1id as [cust1id1],
cust2id as [cust2id1]
from
acct
) t1
join
(
select
acctnumber as [acctnumber2],
date as [date2],
cust1id as [cust1id2],
cust2id as [cust2id2]
from
acct
) t2
on (t1.acctnumber1 != t2.acctnumber2 and
t1.cust1id1 != t2.cust1id2 and
t1.cust1id1 != t2.cust2id2 and
t1.cust2id1 != t2.cust2id2)
group by
cust1id1
最佳答案
我要感谢 Jeff Breadner 提供带有示例数据的 DDL。
您必须逐步运行以下查询,逐个 CTE 并检查中间结果以了解它的作用。它假设 AcctNumber
在给定的表中是唯一的。
首先,我想为每个客户找到最新的帐户。这是一个简单的top-n-per-group
查询,我正在使用 ROW_NUMBER
接近这里。CTE_Customers
通过汇总 Cust1ID
列出所有个人客户的简单列表和 Cust2ID
. CTE_RN
分配他们的行号。 CTE_LatestAccounts
为每个客户提供最新帐户:
+------------------+------------+--------+
| LatestAcctNumber | LatestDT | CustID |
+------------------+------------+--------+
| 10000 | 2016-02-01 | 1110 |
| 10050 | 2017-02-01 | 1111 |
| 10052 | 2017-02-02 | 1112 |
| 10052 | 2017-02-02 | 1113 |
| 7060 | 2017-02-04 | 1114 |
| 7060 | 2017-02-04 | 1115 |
| 10004 | 2016-02-02 | 1116 |
| 10067 | 2017-02-05 | 1117 |
| 10054 | 2017-02-03 | 1118 |
| 10101 | 2017-06-02 | 1119 |
| 10058 | 2017-02-03 | 1120 |
| 10058 | 2017-02-03 | 1121 |
| 10007 | 2016-02-01 | 1122 |
| 10057 | 2017-02-03 | 1123 |
| 10107 | 2017-06-02 | 1124 |
| 10107 | 2017-06-02 | 1125 |
+------------------+------------+--------+
CTE_MaxLatestAccounts
从原始表中取出每一行并将最新帐户加入到其中两次 - 对于
Cust1D
和
Cust2ID
.对于每一对,我都会选择两个最新帐户中的一个——最近的一个。因此,属于一对的客户可能会从其合作伙伴那里获得一个帐户。
+---------+---------+-------------+---------------------+
| Cust1ID | Cust2ID | MaxLatestDT | MaxLatestAcctNumber |
+---------+---------+-------------+---------------------+
| 1110 | NULL | 2016-02-01 | 10000 |
| 1111 | NULL | 2017-02-01 | 10050 |
| 1111 | NULL | 2017-02-01 | 10050 |
| 1120 | NULL | 2017-02-03 | 10058 |
| 1120 | 1121 | 2017-02-03 | 10058 |
| 1112 | NULL | 2017-02-02 | 10052 |
| 1113 | 1112 | 2017-02-02 | 10052 |
| 1114 | 1115 | 2017-02-04 | 7060 |
| 1115 | 1114 | 2017-02-04 | 7060 |
| 1116 | 1117 | 2017-02-05 | 10067 |
| 1117 | NULL | 2017-02-05 | 10067 |
| 1118 | NULL | 2017-02-03 | 10054 |
| 1118 | 1119 | 2017-06-02 | 10101 |
| 1119 | NULL | 2017-06-02 | 10101 |
| 1122 | 1123 | 2017-02-03 | 10057 |
| 1123 | 1124 | 2017-06-02 | 10107 |
| 1124 | 1125 | 2017-06-02 | 10107 |
+---------+---------+-------------+---------------------+
MaxLatestAcctNumber
这里适用于
Cust1ID
和
Cust2ID
.同一客户可能在此处多次列出,我们需要使用最新的帐户再次选择条目。这是一对的最新帐户,不适用于个人客户。
Cust1ID
和
Cust2ID
列表中的客户:
CTE_CustomersWithLatestAccountFromPair
.在
CTE_CustomersWithLatestAccountFromPairRN
中分配行号并在
CTE_FinalAccounts
中选择最终帐户.
+---------------------+
| MaxLatestAcctNumber |
+---------------------+
| 10000 |
| 10050 |
| 10052 |
| 10052 |
| 7060 |
| 7060 |
| 10067 |
| 10067 |
| 10101 |
| 10101 |
| 10058 |
| 10058 |
| 10057 |
| 10107 |
| 10107 |
| 10107 |
+---------------------+
declare @ACCT table (
AcctNumber int,
dt date,
Cust1ID int,
Cust2ID int
);
insert into @ACCT values
(10000, '2016-02-01', 1110, null),
(10001, '2016-02-01', 1111, null),
(10050, '2017-02-01', 1111, null),
(10008, '2016-02-01', 1120, null),
(10058, '2017-02-03', 1120, 1121),
(10002, '2016-02-01', 1112, null),
(10052, '2017-02-02', 1113, 1112),
(10003, '2016-02-02', 1114, 1115),
(7060, '2017-02-04', 1115, 1114),
(10004, '2016-02-02', 1116, 1117),
(10067, '2017-02-05', 1117, null),
(10005, '2016-02-01', 1118, null),
(10054, '2017-02-03', 1118, 1119),
(10101, '2017-06-02', 1119, null),
(10007, '2016-02-01', 1122, 1123),
(10057, '2017-02-03', 1123, 1124),
(10107, '2017-06-02', 1124, 1125);
WITH
CTE_Customers
AS
(
SELECT
AcctNumber
,dt
,Cust1ID AS CustID
FROM @ACCT
WHERE Cust1ID IS NOT NULL
UNION ALL
SELECT
AcctNumber
,dt
,Cust2ID AS CustID
FROM @ACCT
WHERE Cust2ID IS NOT NULL
)
,CTE_RN
AS
(
SELECT
AcctNumber
,dt
,CustID
,ROW_NUMBER() OVER (PARTITION BY CustID ORDER BY dt DESC) AS rn
FROM CTE_Customers
)
,CTE_LatestAccounts
-- this gives one row per CustID
AS
(
SELECT
AcctNumber AS LatestAcctNumber
,dt AS LatestDT
,CustID
FROM CTE_RN
WHERE rn = 1
)
,CTE_MaxLatestAccounts
AS
(
SELECT
A.Cust1ID
,A.Cust2ID
,CASE WHEN ISNULL(A1.LatestDT, '2000-01-01') > ISNULL(A2.LatestDT, '2000-01-01')
THEN A1.LatestDT ELSE A2.LatestDT END AS MaxLatestDT
,CASE WHEN ISNULL(A1.LatestDT, '2000-01-01') > ISNULL(A2.LatestDT, '2000-01-01')
THEN A1.LatestAcctNumber ELSE A2.LatestAcctNumber END AS MaxLatestAcctNumber
FROM
@ACCT AS A
LEFT JOIN CTE_LatestAccounts AS A1 ON A1.CustID = A.Cust1ID
LEFT JOIN CTE_LatestAccounts AS A2 ON A2.CustID = A.Cust2ID
)
,CTE_CustomersWithLatestAccountFromPair
AS
(
SELECT
Cust1ID AS CustID
,MaxLatestDT
,MaxLatestAcctNumber
FROM CTE_MaxLatestAccounts
WHERE Cust1ID IS NOT NULL
UNION ALL
SELECT
Cust2ID AS CustID
,MaxLatestDT
,MaxLatestAcctNumber
FROM CTE_MaxLatestAccounts
WHERE Cust2ID IS NOT NULL
)
,CTE_CustomersWithLatestAccountFromPairRN
AS
(
SELECT
CustID
,MaxLatestDT
,MaxLatestAcctNumber
,ROW_NUMBER() OVER (PARTITION BY CustID ORDER BY MaxLatestDT DESC) AS rn
FROM CTE_CustomersWithLatestAccountFromPair
)
,CTE_FinalAccounts
AS
(
SELECT MaxLatestAcctNumber
FROM CTE_CustomersWithLatestAccountFromPairRN
WHERE rn = 1
)
SELECT *
FROM @ACCT AS A
WHERE A.AcctNumber IN (SELECT MaxLatestAcctNumber FROM CTE_FinalAccounts)
;
+------------+------------+---------+---------+
| AcctNumber | dt | Cust1ID | Cust2ID |
+------------+------------+---------+---------+
| 10000 | 2016-02-01 | 1110 | NULL |
| 10050 | 2017-02-01 | 1111 | NULL |
| 10058 | 2017-02-03 | 1120 | 1121 |
| 10052 | 2017-02-02 | 1113 | 1112 |
| 7060 | 2017-02-04 | 1115 | 1114 |
| 10067 | 2017-02-05 | 1117 | NULL |
| 10101 | 2017-06-02 | 1119 | NULL |
| 10057 | 2017-02-03 | 1123 | 1124 |
| 10107 | 2017-06-02 | 1124 | 1125 |
+------------+------------+---------+---------+
10107
) 的行/帐户,它也可能选择链中间的帐户。在这种情况下,它选择了一行
10057
,而不是
10007
,因为这是客户的后期帐户
1122
和
1123
.
CTE_LatestAccounts
后面的查询基本上运行了四次。
CTE_LatestAccounts
的结果,则很可能放入具有适当索引的临时表中,整体性能会更好。
DECLARE @LatestAccounts TABLE
(LatestAcctNumber int, LatestDT date, CustID int PRIMARY KEY);
WITH
CTE_Customers
AS
(
SELECT
AcctNumber
,dt
,Cust1ID AS CustID
FROM @ACCT
WHERE Cust1ID IS NOT NULL
UNION ALL
SELECT
AcctNumber
,dt
,Cust2ID AS CustID
FROM @ACCT
WHERE Cust2ID IS NOT NULL
)
,CTE_RN
AS
(
SELECT
AcctNumber
,dt
,CustID
,ROW_NUMBER() OVER (PARTITION BY CustID ORDER BY dt DESC) AS rn
FROM CTE_Customers
)
,CTE_LatestAccounts
-- this gives one row per CustID
AS
(
SELECT
AcctNumber AS LatestAcctNumber
,dt AS LatestDT
,CustID
FROM CTE_RN
WHERE rn = 1
)
INSERT INTO @LatestAccounts (LatestAcctNumber, LatestDT, CustID)
SELECT LatestAcctNumber, LatestDT, CustID
FROM CTE_LatestAccounts;
WITH
CTE_MaxLatestAccounts
AS
(
SELECT
A.Cust1ID
,A.Cust2ID
,CASE WHEN ISNULL(A1.LatestDT, '2000-01-01') > ISNULL(A2.LatestDT, '2000-01-01')
THEN A1.LatestDT ELSE A2.LatestDT END AS MaxLatestDT
,CASE WHEN ISNULL(A1.LatestDT, '2000-01-01') > ISNULL(A2.LatestDT, '2000-01-01')
THEN A1.LatestAcctNumber ELSE A2.LatestAcctNumber END AS MaxLatestAcctNumber
FROM
@ACCT AS A
LEFT JOIN @LatestAccounts AS A1 ON A1.CustID = A.Cust1ID
LEFT JOIN @LatestAccounts AS A2 ON A2.CustID = A.Cust2ID
)
,CTE_CustomersWithLatestAccountFromPair
AS
(
SELECT
Cust1ID AS CustID
,MaxLatestDT
,MaxLatestAcctNumber
FROM CTE_MaxLatestAccounts
WHERE Cust1ID IS NOT NULL
UNION ALL
SELECT
Cust2ID AS CustID
,MaxLatestDT
,MaxLatestAcctNumber
FROM CTE_MaxLatestAccounts
WHERE Cust2ID IS NOT NULL
)
,CTE_CustomersWithLatestAccountFromPairRN
AS
(
SELECT
CustID
,MaxLatestDT
,MaxLatestAcctNumber
,ROW_NUMBER() OVER (PARTITION BY CustID ORDER BY MaxLatestDT DESC) AS rn
FROM CTE_CustomersWithLatestAccountFromPair
)
,CTE_FinalAccounts
AS
(
SELECT MaxLatestAcctNumber
FROM CTE_CustomersWithLatestAccountFromPairRN
WHERE rn = 1
)
SELECT *
FROM @ACCT AS A
WHERE A.AcctNumber IN (SELECT MaxLatestAcctNumber FROM CTE_FinalAccounts)
;
关于sql - 查找每个客户组的最新帐户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42119006/
我有一个名为 flightbooking 的表。该表由字段组成,包括标有“R”或“C”的状态、已保留和已取消。 我想弄清楚的是允许删除状态为“C”的记录,但如果下一行的状态为“R”,则不应删除。 [编
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 1年前关闭。 Improve this
研究 PHP/Gearman。我试图了解 Gearman 服务器/进程如何确定什么构成“有效”客户端。 在我看过的文档中,文档显示了许多连接到 Gearman 服务器的客户端。但是,我没有找到任何描述
HBase案例:客户/订单 假设HBase 用于存储客户和订单信息。有两种核心记录类型被摄取:客户记录类型和订单记录类型。 客户记录类型将包含您通常期望的所有内容: 客户编号 客户名称
当运行配方时出现问题并且客户端运行中途挂起时,安装的 Chef 客户端将无法使用。 然后,您可以退出机器、重新启动、清理 Chef pid 文件等,但每次启动 Chef 客户端时都会显示以下消息: C
我正在用Java开发游戏,目前进展顺利。我想尽早实现多人游戏,因此我在此基础上进行构建,而不是在具有大量不同功能的情况下将整个游戏移植到多人游戏中。 我想使其成为客户端/服务器应用程序。 现在,我确定
我正在尝试以编程方式修改 magento 上的现有客户数据,但出现错误,希望有人可以帮助我。 require_once('../app/Mage.php'); ini_set("error_repor
我正在学习 JQuery。我需要创建一个自定义控件。该控件基本上将呈现一些 HTML。有时,我只想获取 HTML。我希望使用以下语法: // Put generated html inside of
我正在尝试以编程方式修改 magento 上的现有客户数据,但出现错误,希望有人可以帮助我。 require_once('../app/Mage.php'); ini_set("error_repor
我想选择表格的一行并插入到另一个现有表格中。(我用的是php和MySql,两张表除了id和timestamp外,其他列都是一样的) 我试着做一个手推车。我希望当有人付款时,从“carret”中选择该客
我想使用 JXTA 实现客户端-服务器架构。服务器部分的配置也将是 3 层。有谁知道开始这个项目的好地方吗? 提前致谢。 最佳答案 JXTA 处理 p2p 连接。这与客户端-服务器方法相反。 据我了解
我需要创建一个 Stripe 客户并为他们订阅一个计划。我查看了 Stripe.js,似乎虽然您可以获得 token ,但除此之外它没有提供任何东西。有可用于节点和 PHP 的库,但为什么不能用于 J
我有一个数据库设计要求,它变得越来越复杂,我需要找出最佳的处理方法。 目前,我有“联系人”,也有“公司”。一个公司可以有多个联系人,但一个联系人只能属于一个公司。这形成了明显的 1:n 关系。但是,联
http://ecc.galengrover.com/programs/facility-rentals/ 在那个页面上,只有那个页面我有一个奇怪的问题。在内容框上方,“所有区域”一词出现在其他文本的
所以,我让这个 CSS 预加载器正常工作。但是,我在将其添加到我的网站时遇到了一些困难。有人可以帮助我理解代码的实现,以允许预加载器成为网站加载前查看的第一个元素。此时预加载器将淡出。预加载器的代码如
考虑以下场景: 有一个 Windows 服务托管一个 WCF 服务。 WCF 服务在客户端和位于不同物理机器上的 AppFabric 服务器之间提供接口(interface)。它检索对象,对其进行计算
当前端的订单历史页面 (*/sales/order/history/) 只显示一条短消息时,这个问题首先被意识到:您没有下订单。 经过一番调试,发现问题出在这个函数上: Mage::getSingle
我的公司是一些项目的定制开发商店,有些较大,有些较小。目前,我们通过电子邮件处理所有客户通信。所以我们通过电子邮件发送设计文档,他们将其标记并发送回去。然后我们推出了他们产品的测试版,他们通过电子邮件
我有一个小部件 View 如下: 公共(public)类 RemoteNumView 扩展了 FrameLayout { 我如何调用 Roboguice 就像在 RoboActivity 中一样?如下
我有一个包含客户编号、客户名称和商品编号的 MySQL 表。它比这稍微复杂一点,但我尝试稍微简化它并删除敏感数据。 当前表 Unique Customer Number | Customer Name
我是一名优秀的程序员,十分优秀!