ZS-Tech
asked on
SQL join by date
We have been asked to create a phone log report, in which I need to tie our system database to our phone system database. Both systems run Microsoft SQL 2005. I am not a SQL novice, but I am no expert either. Here is what I have...
A legal database with 2 tables
Table: Claims
ClaimID (PK)
FileNumber
Table Comments:
CommentID (PK)
ClaimID
Comment - The comments I will be pulling are associated with a phone call
Comment Date and Time
Our phone system has a CallLog table.
CallID
StartTime
StopTime
AccountCode - the account code is populated with FileNumbers from the claim table above
My goal is to create a report that will look like this:
FileNumber
Comment
CallDuration
I have joined the Claim table to the CallLog table, and everything works great if there is only one 'call' comment per day (the report is daily). My problem is when there is more than one call on a Claim per day...
What I would like is this...(each line representing an individual call)
ClaimA 11/14 8:00AM 20 (duration)
ClaimA 11/14 10:00AM 100 (duration)
Claim A 11/14 12:00PM 150 (duration)
What I am getting is this...(appears to just grab the first time)
ClaimA 11/14 8:00AM 20 (duration)
ClaimA 11/14 10:00AM 20(duration)
Claim A 11/14 12:00PM 20 (duration)
I realize my join isn't ideal, but is there anyway to the data so I get results that I want?
A legal database with 2 tables
Table: Claims
ClaimID (PK)
FileNumber
Table Comments:
CommentID (PK)
ClaimID
Comment - The comments I will be pulling are associated with a phone call
Comment Date and Time
Our phone system has a CallLog table.
CallID
StartTime
StopTime
AccountCode - the account code is populated with FileNumbers from the claim table above
My goal is to create a report that will look like this:
FileNumber
Comment
CallDuration
I have joined the Claim table to the CallLog table, and everything works great if there is only one 'call' comment per day (the report is daily). My problem is when there is more than one call on a Claim per day...
What I would like is this...(each line representing an individual call)
ClaimA 11/14 8:00AM 20 (duration)
ClaimA 11/14 10:00AM 100 (duration)
Claim A 11/14 12:00PM 150 (duration)
What I am getting is this...(appears to just grab the first time)
ClaimA 11/14 8:00AM 20 (duration)
ClaimA 11/14 10:00AM 20(duration)
Claim A 11/14 12:00PM 20 (duration)
I realize my join isn't ideal, but is there anyway to the data so I get results that I want?
I have deliberately setup sample data where:
a Claim exists with no calls
a call exists with no claim
Below are results of 4 query variants, the purpose being I'm trying to understand what you consider to be important
a Claim exists with no calls
a call exists with no claim
Below are results of 4 query variants, the purpose being I'm trying to understand what you consider to be important
([ClaimID] int, [FileNumber] varchar(20))
;
INSERT INTO Claims
([ClaimID], [FileNumber])
VALUES
(1, 'Claim A'),
(2, 'Claim B')
;
CREATE TABLE CallLog
([CallID] int, [StartTime] datetime, [StopTime] datetime, [AccountCode] varchar(20))
;
INSERT INTO CallLog
([CallID], [StartTime], [StopTime], [AccountCode])
VALUES
(1, '2013-10-23 09:00:00', '2013-10-23 09:20:00', 'Claim A'),
(2, '2013-10-23 09:00:00', '2013-10-23 09:20:00', NULL)
;
CREATE TABLE Comments
([CommentID] int, [ClaimID] int, [Comment] varchar(200), [Comment_DT] datetime)
;
INSERT INTO Comments
([CommentID], [ClaimID], [Comment], [Comment_DT])
VALUES
(1, 1, '- The comments I will be pulling are associated with a phone call', '2013-10-23 09:15:00')
;
**Query 1**:
select
Claims.FileNumber
, Comments.Comment
, datediff(minute,CallLog.StartTime,CallLog.StopTime) as Call_Duration_Min
, convert(varchar,CallLog.StartTime,120) as Call_Start
from Claims
inner join CallLog on Claims.FileNumber = CallLog.AccountCode
left join Comments on Claims.ClaimID = comments.ClaimID
**[Results][2]**:
| FILENUMBER | COMMENT | CALL_DURATION_MIN | CALL_START |
|------------|-------------------------------------------------------------------|-------------------|---------------------|
| Claim A | - The comments I will be pulling are associated with a phone call | 20 | 2013-10-23 09:00:00 |
**Query 2**:
select
Claims.FileNumber
, Comments.Comment
, datediff(minute,CallLog.StartTime,CallLog.StopTime) as Call_Duration_Min
, convert(varchar,CallLog.StartTime,120) as Call_Start
from Claims
left join CallLog on Claims.FileNumber = CallLog.AccountCode
left join Comments on Claims.ClaimID = comments.ClaimID
**[Results][3]**:
| FILENUMBER | COMMENT | CALL_DURATION_MIN | CALL_START |
|------------|-------------------------------------------------------------------|-------------------|---------------------|
| Claim A | - The comments I will be pulling are associated with a phone call | 20 | 2013-10-23 09:00:00 |
| Claim B | (null) | (null) | (null) |
**Query 3**:
select
Claims.FileNumber
, Comments.Comment
, datediff(minute,CallLog.StartTime,CallLog.StopTime) as Call_Duration_Min
, convert(varchar,CallLog.StartTime,120) as Call_Start
from CallLog
inner join Claims on CallLog.AccountCode = Claims.FileNumber
left join Comments on Claims.ClaimID = comments.ClaimID
**[Results][4]**:
| FILENUMBER | COMMENT | CALL_DURATION_MIN | CALL_START |
|------------|-------------------------------------------------------------------|-------------------|---------------------|
| Claim A | - The comments I will be pulling are associated with a phone call | 20 | 2013-10-23 09:00:00 |
**Query 4**:
select
Claims.FileNumber
, Comments.Comment
, datediff(minute,CallLog.StartTime,CallLog.StopTime) as Call_Duration_Min
, convert(varchar,CallLog.StartTime,120) as Call_Start
from CallLog
left join Claims on CallLog.AccountCode = Claims.FileNumber
left join Comments on Claims.ClaimID = comments.ClaimID
**[Results][5]**:
| FILENUMBER | COMMENT | CALL_DURATION_MIN | CALL_START |
|------------|-------------------------------------------------------------------|-------------------|---------------------|
| Claim A | - The comments I will be pulling are associated with a phone call | 20 | 2013-10-23 09:00:00 |
| (null) | (null) | 20 | 2013-10-23 09:00:00 |
[1]: http://sqlfiddle.com/#!3/48114/9
By the way, the question title "SQL join by date" might indicate something entirely different
but
but
My goal is to create a report that will look like this:
FileNumber
Comment
CallDuration
That report layout does not seem to relate to the title.
FileNumber
Comment
CallDuration
zs, in order for us to help, I think you will need to post some sample data so that we can tell why the results you expect are not the results you are getting. In the example you give, I have no way of knowing why the numbers are wrong.
For example, I would use this query:
select c.filenumber, cm.comment, cl.starttime, (cl.stoptime-cl.starttime) duration
from CallLog cl join claims c on (cl.accountcode=c.filenumb er)
join comments cm on (c.claimid=cm.claimID)
For example, I would use this query:
select c.filenumber, cm.comment, cl.starttime, (cl.stoptime-cl.starttime)
from CallLog cl join claims c on (cl.accountcode=c.filenumb
join comments cm on (c.claimid=cm.claimID)
ASKER
CREATE TABLE [dbo].[XCLAIMS](
[ClaimID] [int] IDENTITY(1,1) NOT NULL,
[FileNumber] [varchar](10) NULL,
CONSTRAINT [PK_XCLAIMS] PRIMARY KEY CLUSTERED
(
[ClaimID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[XCALLS](
[CallID] [int] IDENTITY(1,1) NOT NULL,
[StartTime] [datetime] NULL,
[StopTime] [datetime] NULL,
[AccountCode] [varchar](10) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[XCOMMENTS](
[CommentID] [int] IDENTITY(1,1) NOT NULL,
[ClaimID] [int] NULL,
[Comment] [varchar](50) NULL,
[CommentDate] [datetime] NULL,
CONSTRAINT [PK_XComment] PRIMARY KEY CLUSTERED
(
[CommentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
insert into xclaims (filenumber)
values ('11-11111')
insert into xclaims (filenumber)
values ('12-22222')
insert into xclaims (filenumber)
values ('13-33333')
insert into xcomments (claimid,comment,commentda te)
values (1,'Made Contact','2013-11-14 08:00:00.000')
insert into xcomments (claimid,comment,commentda te)
values (1,'Made Contact Again','2013-11-14 10:00:00.000')
insert into xcomments (claimid,comment,commentda te)
values (1,'Made Contact Yet Again','2013-11-14 12:00:00.000')
insert into xcalls (starttime,stoptime,accoun tcode)
values ('2013-11-14 07:59:00.000','2013-11-14 08:05:00.000','11-11111')
insert into xcalls (starttime,stoptime,accoun tcode)
values ('2013-11-14 09:58:00.000','2013-11-14 10:06:00.000','11-11111')
insert into xcalls (starttime,stoptime,accoun tcode)
values ('2013-11-14 11:57:00.000','2013-11-14 12:07:00.000','11-11111')
I guess what I was getting at in my original post about 'joining by date', is that i'm trying to associate the xcomment.commentdate to the closest xcalls.starttime.
ok...so my bad query and results...
select xclaims.filenumber,xcommen ts.comment ,-(datedif f(second,x calls.stop time,xcall s.starttim e)) as duration
from xclaims inner join
xcomments on xclaims.claimid=xcomments. claimid inner join
xcalls on xclaims.filenumber = xcalls.accountcode
filenumber comment duration
11-11111 Made Contact 360
11-11111 Made Contact 480
11-11111 Made Contact 600
11-11111 Made Contact Again 360
11-11111 Made Contact Again 480
11-11111 Made Contact Again 600
11-11111 Made Contact Yet Again 360
11-11111 Made Contact Yet Again 480
11-11111 Made Contact Yet Again 600
What I want is
filenumber comment duration
11-11111 Made Contact 360
11-11111 Made Contact Again 480
11-11111 Made Contact Yet Again 600
[ClaimID] [int] IDENTITY(1,1) NOT NULL,
[FileNumber] [varchar](10) NULL,
CONSTRAINT [PK_XCLAIMS] PRIMARY KEY CLUSTERED
(
[ClaimID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[XCALLS](
[CallID] [int] IDENTITY(1,1) NOT NULL,
[StartTime] [datetime] NULL,
[StopTime] [datetime] NULL,
[AccountCode] [varchar](10) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[XCOMMENTS](
[CommentID] [int] IDENTITY(1,1) NOT NULL,
[ClaimID] [int] NULL,
[Comment] [varchar](50) NULL,
[CommentDate] [datetime] NULL,
CONSTRAINT [PK_XComment] PRIMARY KEY CLUSTERED
(
[CommentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
insert into xclaims (filenumber)
values ('11-11111')
insert into xclaims (filenumber)
values ('12-22222')
insert into xclaims (filenumber)
values ('13-33333')
insert into xcomments (claimid,comment,commentda
values (1,'Made Contact','2013-11-14 08:00:00.000')
insert into xcomments (claimid,comment,commentda
values (1,'Made Contact Again','2013-11-14 10:00:00.000')
insert into xcomments (claimid,comment,commentda
values (1,'Made Contact Yet Again','2013-11-14 12:00:00.000')
insert into xcalls (starttime,stoptime,accoun
values ('2013-11-14 07:59:00.000','2013-11-14 08:05:00.000','11-11111')
insert into xcalls (starttime,stoptime,accoun
values ('2013-11-14 09:58:00.000','2013-11-14 10:06:00.000','11-11111')
insert into xcalls (starttime,stoptime,accoun
values ('2013-11-14 11:57:00.000','2013-11-14 12:07:00.000','11-11111')
I guess what I was getting at in my original post about 'joining by date', is that i'm trying to associate the xcomment.commentdate to the closest xcalls.starttime.
ok...so my bad query and results...
select xclaims.filenumber,xcommen
from xclaims inner join
xcomments on xclaims.claimid=xcomments.
xcalls on xclaims.filenumber = xcalls.accountcode
filenumber comment duration
11-11111 Made Contact 360
11-11111 Made Contact 480
11-11111 Made Contact 600
11-11111 Made Contact Again 360
11-11111 Made Contact Again 480
11-11111 Made Contact Again 600
11-11111 Made Contact Yet Again 360
11-11111 Made Contact Yet Again 480
11-11111 Made Contact Yet Again 600
What I want is
filenumber comment duration
11-11111 Made Contact 360
11-11111 Made Contact Again 480
11-11111 Made Contact Yet Again 600
how can you know which comment refers to which call? Both are linked to the claimID, but there is no direct linkage between the call and the comment. In this example, we know that there are only 3 calls, and we can figure out from context which belongs to which.
For example, how do you know that the comment
values ('2013-11-14 11:57:00.000','2013-11-14 12:07:00.000','11-11111')
refers to
values (1,'Made Contact Yet Again','2013-11-14 12:00:00.000')
and not to
values (1,'Made Contact Again','2013-11-14 10:00:00.000')
See http://sqlfiddle.com/#!6/13824/6
For example, how do you know that the comment
values ('2013-11-14 11:57:00.000','2013-11-14 12:07:00.000','11-11111')
refers to
values (1,'Made Contact Yet Again','2013-11-14 12:00:00.000')
and not to
values (1,'Made Contact Again','2013-11-14 10:00:00.000')
See http://sqlfiddle.com/#!6/13824/6
ASKER
Yeah, that appears to be my roadblock. I need to find an elegant way to get the commentid into the call log table, so that everything can be joined up properly. I guess, at best, I was just hoping to find a shortcut way around that.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Scott, that worked perfectly. I really appreciate your help on this. (P.S. I would have never figured that out)
That assumes that the comments were entered in the same order that the phone calls were made.
and it does not account for calls made without comments recorded, add this to the sample:
insert into xcalls (starttime,stoptime,accoun tcode)
values ('2013-11-15 10:11:12.000','2013-11-15 10:15:23.000','11-11111')
The call and duration should be seen in the result:
insert into xcalls (starttime,stoptime,accoun
values ('2013-11-15 10:11:12.000','2013-11-15 10:15:23.000','11-11111')
The call and duration should be seen in the result:
| FILENUMBER | COMMENT | DURATION |
|------------|------------------------|----------|
| 11-11111 | Made Contact | 360 |
| 11-11111 | Made Contact Again | 480 |
| 11-11111 | Made Contact Yet Again | 600 |
| 11-11111 | (null) | 251 |
-- produced by
SELECT
filenumber
, comment
, duration
FROM (
SELECT
xcl.filenumber
, xco.comment
, (DATEDIFF(SECOND, xca.starttime, xca.stoptime)) AS duration
, row_number() over (partition BY xca.callid ORDER BY xco.CommentID) AS rn
FROM dbo.XCALLS xca
INNER JOIN dbo.XCLAIMS xcl
ON xca.AccountCode = xcl.filenumber
LEFT JOIN XCOMMENTS xco
ON xca.AccountCode = xcl.filenumber
AND xco.commentdate between xca.starttime and xca.stoptime
) x
WHERE rn = 1
;
You could do this:
select * from Claims
inner join CallLog on Claims.FileNumber = CallLog.AccountCode
or this:
select * from Claims
left join CallLog on Claims.FileNumber = CallLog.AccountCode
or you could reverse the table positions and each variant could give you slightly different results (depending on data quality basically)
Is the primary focus claim or call? e.g.
Are you selecting for a particular Claim (or set of claims)?
or
Are you selecting over a range of dates and want to know what claims are involved?
I assume it does not matter that if no call is made on a date then that date is not listed.