TSQL查找连续3个月内发生的订单
请帮助我生成以下查询。假设我有客户表和订单表。
客户表
CustID CustName
1 AA
2 BB
3 CC
4 DD
订单表
OrderID OrderDate CustID
100 01-JAN-2000 1
101 05-FEB-2000 1
102 10-MAR-2000 1
103 01-NOV-2000 2
104 05-APR-2001 2
105 07-MAR-2002 2
106 01-JUL-2003 1
107 01-SEP-2004 4
108 01-APR-2005 4
109 01-MAY-2006 3
110 05-MAY-2007 1
111 07-JUN-2007 1
112 06-JUL-2007 1
我想找出连续三个月下过订单的客户。 (允许使用SQL Server 2005和2008进行查询)。
期望的输出是:
CustName Year OrderDate
AA 2000 01-JAN-2000
AA 2000 05-FEB-2000
AA 2000 10-MAR-2000
AA 2007 05-MAY-2007
AA 2007 07-JUN-2007
AA 2007 06-JUL-2007
Please help me to generate the following query. Say I have customer table and order table.
Customer Table
CustID CustName
1 AA
2 BB
3 CC
4 DD
Order Table
OrderID OrderDate CustID
100 01-JAN-2000 1
101 05-FEB-2000 1
102 10-MAR-2000 1
103 01-NOV-2000 2
104 05-APR-2001 2
105 07-MAR-2002 2
106 01-JUL-2003 1
107 01-SEP-2004 4
108 01-APR-2005 4
109 01-MAY-2006 3
110 05-MAY-2007 1
111 07-JUN-2007 1
112 06-JUL-2007 1
I want to find out the customers who have made orders on three successive months. (Query using SQL server 2005 and 2008 is allowed).
The desired output is:
CustName Year OrderDate
AA 2000 01-JAN-2000
AA 2000 05-FEB-2000
AA 2000 10-MAR-2000
AA 2007 05-MAY-2007
AA 2007 07-JUN-2007
AA 2007 06-JUL-2007
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
编辑:摆脱了
MAX() OVER (PARTITION BY ...)
,因为这似乎会降低性能。Edit: Got rid or the
MAX() OVER (PARTITION BY ...)
as that seemed to kill performance.这是我的版本。我确实只是出于好奇才提出这个问题,以展示思考问题的另一种方式。事实证明它比这更有用,因为它的性能甚至比马丁·史密斯(Martin Smith)很酷的“分组岛屿”解决方案还要好。不过,一旦他摆脱了一些过于昂贵的聚合窗口函数并进行了真正的聚合,他的查询就开始起作用了。
解决方案 1: 运行 3 个月或更长时间,通过检查前后 1 个月并使用半连接来完成。
解决方案 2: 精确的 3 个月模式。如果运行时间为 4 个月或更长时间,则排除这些值。这是通过检查提前两个月和落后两个月来完成的(本质上是寻找模式 N,Y,Y,Y,N)。
如果其他人想玩的话,这是我的表加载脚本:
性能
以下是 3 个月或以上查询的一些性能测试结果:
这只是每个运行一次,但数字是颇具代表性。事实证明,您的查询的性能毕竟并没有那么糟糕,丹尼斯。马丁的查询轻而易举地击败了其他查询,但首先使用的是他修复的一些过于昂贵的窗口函数策略。
当然,正如我所指出的,当客户在同一天有两个订单时,丹尼斯的查询不会提取正确的行,因此除非他修复了这一问题,否则他的查询不会出现争用。
此外,不同的指数也可能会带来变化。我不知道。
Here is my version. I really was presenting this as a mere curiosity, to show another way of thinking about the problem. It turned out to be more useful than that because it performed better than even Martin Smith's cool "grouped islands" solution. Though, once he got rid of some overly expensive aggregate windowing functions and did real aggregates instead, his query started kicking butt.
Solution 1: Runs of 3 months or more, done by checking 1 month ahead and behind and using a semi-join against that.
Solution 2: Exact 3-month patterns. If it is a 4-month or greater run, the values are excluded. This is done by checking 2 months ahead and two months behind (essentially looking for the pattern N, Y, Y, Y, N).
Here's my table-loading script if anyone else wants to play:
Performance
Here are some performance testing results for the 3-month-or-more queries:
This is only one run of each, but the numbers are fairly representative. It turns out that your query wasn't so badly-performing, Denis, after all. Martin's query beats the others hands down, but at first was using some overly-expensive windowing functions strategies that he fixed.
Of course, as I noted, Denis's query isn't pulling the right rows when a customer has two orders on the same day, so his query is out of contention unless he fixed is.
Also, different indexes could possibly shake things up. I don't know.
干得好:
Here you go:
这是我的看法。
Here is my take.