Click here to Skip to main content
15,913,027 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
i have 3 tables : Documents, Users and Replies

Documents table
SQL
docid docName   sendTo
1     vacation  1            
2     private   1


Users table
SQL
userid userName
1      john
2      marry


Replies table
SQL
replyid docid userid replyDate
1       1      1      14-06-2015
2       1      2      15-60-2015


how can i create query get the count of replies with last reply date
when i choose senderid of document=1 (john) appear like this :

SQL
docName   numOfReplies lastReply
vacation   2           15-06-2015
private    0           null


how can i do that to get this result?



EDIT: AL) from comments
This is what I have tried so far:
SQL
SELECT distinct 
  dbo.Documents.DocName, 
  COUNT(*) over () AS [numOfReplies],
  max(dbo.Replies,replyDate) as [lastreply]
FROM 
  dbo.Documents 
  INNER JOIN dbo.Replies ON dbo.Documents.DocumentID = dbo.Replies.DocumentID 
  INNER JOIN dbo.Users ON dbo.Documents.SendTo = dbo.Users.UserID
WHERE 
  dbo.Users.UserID = 1
GROUP BY 
  dbo.Documents.DocumentID
Posted
Updated 15-Jun-15 0:30am
v2
Comments
Tomas Takac 15-Jun-15 5:34am    
What have you tried so far? Where are you stuck?
tranesyasd 15-Jun-15 5:41am    
SELECT distinct dbo.Documents.DocName, COUNT(*) over () AS [numOfReplies],max(dbo.Replies,replyDate) as [lastreply]
FROM dbo.Documents INNER JOIN
dbo.Replies ON dbo.Documents.DocumentID = dbo.Replies.DocumentID INNER JOIN
dbo.Users ON dbo.Documents.SendTo = dbo.Users.UserID
WHERE (dbo.Users.UserID = 1)
GROUP BY dbo.Documents.DocumentID

Try something like this:
SQL
WITH cteCounts As
(
    SELECT
        DocumentID,
        Count(*) As numOfReplies,
        Max(ReplyDate) As lastReply
    FROM
        dbo.Replies
    GROUP BY
        DocumentID
)
SELECT
    D.DocName,
    C.numOfReplies,
    C.lastReply
FROM
    dbo.Documents As D
    LEFT JOIN cteCounts As C
    ON C.DocumentID = D.DocumentID
WHERE
    D.SendTo = 1
;
 
Share this answer
 
I'll point out some of the problems first:

- There is a mistake in your sample data - 15-60-2015 is not a valid date

- In your attempt the syntax for MAX is incorrect - you've used a comma instead of a period. It should be
max(dbo.Replies.replyDate) as [lastreply]


- In your example SQL you have used column DocumentID but the table has docId

- Your expected results do not depend on UserId at all - they are the totals / max date per document type.

The key seems to be that you want to see all document types regardless of whether they appear in the Replies table. You can get those as follows
SQL
;WITH CTE AS
(
    select docid, count(replyid) as num, max(replyDate) as maxDate
    from Replies
    GROUP BY docid
)
SELECT docName, isnull(num,0), maxDate
FROM Documents D
LEFT OUTER JOIN CTE ON D.docid = CTE.docid
The query above gives your expected results as shown. Note there is no reference to userId

If, however, what you want is the details for a particular user then introduce UserId into the mix as follows
SQL
;WITH CTE AS
(
    select userid, docid, count(replyid) as num, max(replyDate) as maxDate
    from Replies
    GROUP BY docid, userid
)
SELECT docName, isnull(num,0), maxDate
FROM Documents D
LEFT OUTER JOIN CTE ON D.docid = CTE.docid
WHERE userid = 1 OR userid is null
Which gives results of
vacation    1   2015-06-14
private     0   NULL
Note the different date.

[EDIT - after OP request for further information]
To get the difference in dates in the format you've suggested is quite simple but can make the SQL look a little messy. I've pulled the messy bit into a 2nd common table expression to (hopefully) make it clear what is going on :
;WITH CTE AS
(
    select userid, docid, count(replyid) as num, max(replyDate) as maxDate
    from Replies
    GROUP BY docid, userid
),
CTE2 AS
(
	SELECT CTE.userid, docName, isnull(num,0) as numOfReplies, maxDate
	,DateDiff(dd, maxDate, getdate())      As days
		 , DateDiff(hh, maxDate, getdate()) % 24 As hours
		 , DateDiff(mi, maxDate, getdate()) % 60 As mins
	FROM Documents D
	LEFT OUTER JOIN CTE ON D.docid = CTE.docid
)
SELECT CTE2.docName, CTE2.numOfReplies,
Res = '(' + RTRIM((CASE WHEN CTE2.days > 0 THEN CAST(CTE2.days as varchar) + 'd ' END) 
	 + (CASE WHEN CTE2.hours > 0 THEN CAST(CTE2.hours as varchar) + 'h ' END)
	 + (CASE WHEN CTE2.mins > 0 THEN CAST(CTE2.mins as varchar) + 'm' END))
	+ ')'
from CTE2
WHERE userid = 1 OR userid is null

By way of explanation - use the DATEDIFF function to work out the number of days since MaxDate and Now. Use the same function modulo 24 to get the remaining number of (whole) hours over and above that number of days, and datediff modulo 60 to get the minutes over and above the number of days and hours. Be aware that time is ticking in that part of the sql - each call to getdate() will return a subtly different value, so don't go down to the millisecond level of comparison!

The final part of the query is just trying to get the output formatted. Under normal circumstances I would do that (i.e. output formatting) in my calling program e.g. probably something like
C#
var res = new StringBuilder("(");
res.Append((days != 0) ? string.Format("{0}d ", days) : "");
res.Append((hours != 0) ? string.Format("{0}h ", hours) : "");
res.Append((mins != 0) ? string.Format("{0}d ", mins) : "");
res.Append(")");
Console.WriteLine(res.ToString().Replace(" )", ")"));
 
Share this answer
 
v2
Comments
tranesyasd 16-Jun-15 6:19am    
thank you very much
but if i need to get the last reply like this (1d 10h) of (1h 15m) instead of the date itself (15-6-2015)
CHill60 16-Jun-15 7:28am    
There are no times in your data - where would this information come from?
tranesyasd 17-Jun-15 1:53am    
come from the difference between the DatTime.Now and the lastReply
if the datetime.now is 17-06-2015 09:00:00 and the lastReply is 15-06-2015 08:00:00
the result be like this (2d 1h)
CHill60 17-Jun-15 5:55am    
I've updated my solution
tranesyasd 18-Jun-15 4:04am    
thank you very much

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900