[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 330
  • Last Modified:

Trying to develop a query in SQL which finds the time frame between two dates with added criteria

Ok  I want to find the number of days between a cancellation and purchase without including repeat cancellations...

So if new customer then initial value for purchase history = A
If they looked at data put it in cart and no purchase = B
Purchase = C

So I want to get the following data from a pattern

new customer       A
1-Jan-14                     C
2-Jan-14                     B
3-Jan-14                     C
4-Jan-14                 C
5-Jan-14                     B
6-Jan-14                     C
7-Jan-14                     B
8-Jan-14                     B
9-Jan-14                     B
10-Jan-14                     C

So I would like to know the results of days between every instance of B if it follows a C or A. Without getting results for any B which follows a B.

IE the January 7 B had a C appointment three days later.
I would get no results from the Jan 8 or 9th B.
0
Sean Meyer
Asked:
Sean Meyer
  • 2
2 Solutions
 
PortletPaulCommented:
are you using SQL Server 2012 or later? (the LEAD() function might help solve this)
0
 
PortletPaulCommented:
Here is an approach using a CTE and a self-join. I have included a third column (clientID) as I presume something like that will be present and will be needed.

Here's my result, note the "dayz" is calculated as a duration, it may be 1 day more than you want (that can be fixed):
| RN |   C2RN | ACODE | C2CODE |      ADATE |     C2DATE |   DAYZ |
|----|--------|-------|--------|------------|------------|--------|
|  1 |      2 |     A |      C | 2014-01-01 | 2014-01-01 |      1 |
|  2 |      3 |     C |      C | 2014-01-01 | 2014-01-01 |      1 |
|  3 |      4 |     C |      B | 2014-01-01 | 2014-01-02 |      2 |
|  5 |      6 |     B |      C | 2014-01-02 | 2014-01-03 |      2 |
|  6 |      7 |     C |      C | 2014-01-03 | 2014-01-03 |      1 |
|  7 |      8 |     C |      C | 2014-01-03 | 2014-01-04 |      2 |
|  8 |      9 |     C |      C | 2014-01-04 | 2014-01-04 |      1 |
|  9 |     10 |     C |      B | 2014-01-04 | 2014-01-05 |      2 |
| 11 |     12 |     B |      C | 2014-01-05 | 2014-01-06 |      2 |
| 12 |     13 |     C |      C | 2014-01-06 | 2014-01-06 |      1 |
| 13 |     14 |     C |      B | 2014-01-06 | 2014-01-07 |      2 |
| 19 |     20 |     B |      C | 2014-01-09 | 2014-01-10 |      2 |
| 20 |     21 |     C |      C | 2014-01-10 | 2014-01-10 |      1 |
| 21 | (null) |     C | (null) | 2014-01-10 |     (null) | (null) |

Open in new window

and here is the query for that:
with CTE as (
  select
  *
  , row_number() over(partition by clientid order by adate ASC) as rn
  from aTable
  )
select
        c1.rn
      , c2.rn c2rn
      , c1.acode
      , c2.acode c2code
      , c1.adate
      , c2.adate c2date
      , datediff(day,c1.adate, c2.adate) + 1 as dayz
from CTE c1
left join CTE c2 on c1.rn + 1 = c2.rn
where NOT (c1.acode = 'B' and c2.acode = 'B')
;

-- more details


CREATE TABLE aTable
	([aDate] date, [aCode] varchar(1), clientID int)
;
	
INSERT INTO aTable
	([aDate], [aCode])
VALUES
	('2014-01-01 00:00:00', 'A'),
	('2014-01-01 00:00:00', 'C'),
	('2014-01-02 00:00:00', 'B'),
	('2014-01-03 00:00:00', 'C'),
	('2014-01-04 00:00:00', 'C'),
	('2014-01-05 00:00:00', 'B'),
	('2014-01-06 00:00:00', 'C'),
	('2014-01-07 00:00:00', 'B'),
	('2014-01-08 00:00:00', 'B'),
	('2014-01-09 00:00:00', 'B'),
	('2014-01-10 00:00:00', 'C'),
	('2014-01-01 00:00:00', 'C'),
	('2014-01-02 00:00:00', 'B'),
	('2014-01-03 00:00:00', 'C'),
	('2014-01-04 00:00:00', 'C'),
	('2014-01-05 00:00:00', 'B'),
	('2014-01-06 00:00:00', 'C'),
	('2014-01-07 00:00:00', 'B'),
	('2014-01-08 00:00:00', 'B'),
	('2014-01-09 00:00:00', 'B'),
	('2014-01-10 00:00:00', 'C')
;

update aTable
set clientID = 1
;
http://sqlfiddle.com/#!6/ed097/1

Open in new window

0
 
chaauCommented:
I am not really sure if I understood your question correctly. This query gets you all B's with the number of days to the following C (or A):
;with crn as(
  SELECT *,
  ROW_NUMBER() OVER(ORDER BY dt) rn FROM Table1 ),
c as(
  SELECT dt, purchase, rn, ' ' as prePurchase, dt as preDt 
  FROM crn where rn = 1
  UNION ALL
  SELECT crn.dt, crn.purchase, crn.rn, c.purchase as prePurchase,
  CASE WHEN c.purchase = 'B' THEN c.preDT ELSE crn.dt END
  FROM crn INNER JOIN c ON c.rn + 1 = crn.rn)
select predt as dt, prepurchase as purchase, datediff(day, predt, dt) as diff
from c
where purchase in ('A', 'C') and prepurchase = 'B'

Open in new window

Results:
|                             DT | PURCHASE | DIFF |
|--------------------------------|----------|------|
| January, 02 2014 00:00:00+0000 |        B |    1 |
| January, 05 2014 00:00:00+0000 |        B |    1 |
| January, 07 2014 00:00:00+0000 |        B |    3 |

Open in new window

SQL Fiddle
0
 
awking00Commented:
What are the desired results for your sample data?
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now