How to count something in a mysql procedure? - mysql

I have written a procedure that shows me the image path from picture table and I want to calculate the no. of unread messages.Here is what i am doing
CREATE PROCEDURE datehate.dashboard_message(IN UserID INT)
BEGIN
SELECT picture.path_thumb,status
FROM picture,message,user_profile
WHERE (
(message.receiver_user_id=UserID)
AND
(user_profile.user_id=message.sender_user_id AND picture.picture_id=user_profile.picture_id)
);
END
And this the output i am getting
path_thumb status
E:\DateOrHateUser\DEMO_2_Stockhlom\images\Male\1#j... UNREAD
E:\DateOrHateUser\DEMO_2_Stockhlom\images\Male\3#j... READ
E:\DateOrHateUser\DEMO_2_Stockhlom\images\Male\5#j... UNREAD

use
SELECT count(*)
to get the number of records returned
and put
status="UNREAD"
in your WHERE condition

How about -
CREATE PROCEDURE datehate.dashboard_message(IN UserID INT)
BEGIN
SELECT p.path_thumb, SUM(IF(m.status = 'UNREAD', 1, 0)) AS unread_msgs
FROM message m
INNER JOIN user_profile up
ON m.sender_user_id = up.user_id
INNER JOIN picture p
ON up.picture_id = p.picture_id
WHERE m.receiver_user_id=UserID
GROUP BY m.sender_user_id, p.path_thumb;
END
EDIT I have modified the above query to give the count of unread messages without excluding senders for whom you have no unread messages. Sorry, I misunderstood your question.
or this which will give you the count of messages in each status -
CREATE PROCEDURE datehate.dashboard_message(IN UserID INT)
BEGIN
SELECT p.path_thumb, m.status, COUNT(*) AS msgs
FROM message m
INNER JOIN user_profile up
ON m.sender_user_id = up.user_id
INNER JOIN picture p
ON up.picture_id = p.picture_id
WHERE m.receiver_user_id=UserID
GROUP BY m.sender_user_id, p.path_thumb, m.status;
END

Related

Not getting the expected result when using mysqlQuery duplicate some values

I am trying to fetch data from 4 tables and I wrote one query
SELECT
c.id,
c.name,
c.price,
c.duration,
c.period,
c.practical_classes,
c.theory_classes,
e.id,e.created_at,
u.id,
u.registration_no,
i.id,
i.amountpaid,
(i.amount - i.amountpaid) as balanceamount
FROM
courses c,
coursesenrolled e,
users u,
invoices i
WHERE e.student = "11"
AND e.course = c.id
AND c.delete_status = "0"
AND c.status = "Available"
AND u.id = "11"
AND i.student = e.student
and I am getting the result is like below image here raws are duplicating. if I add GROUP BY in my query the last 3 columns getting the wrong data
the below result which I am getting if I add Group By
Below I am attaching the table format
1. "Course",
2. "coursesenrolled" which is handling data which course is assigned to which users
3."user"
4. invoices which will handling invoice for users
I try to understand the question, so you wanna get the result for user with id=11, right? Try this one
SELECT DISTINCT c.id,c.name,c.price,c.duration,c.period,c.practical_classes,c.theory_classes,e.id,e.created_at,u.id,u.registration_no,i.id,i.amountpaid,(i.amount-i.amountpaid) as balanceamount FROM courses AS c INNER JOIN coursesenrolled AS e ON e.course=c.id INNER JOIN users AS u ON u.id=e.student INNER JOIN invoices AS i ON i.student=u.id WHERE u.id='11' AND c.delete_status='0' AND c.status='Available';

Case statement causing duplicate rows

I've successfully built messaging functionality into my application, I have a small issue which I need assistance on, when I send an email to another user I insert this message into the database, the column ReadDate for this row will be null due to it being new, when I read this message from the UI the ReadDate column will then be populated with today's date.
Now my issue is this, given the below query, which returns emails inside someones inbox where ReceipientId = #UserId passed in. :
Select p.Id [SenderId], p.Username, count(mr.RecipientId) [TotalMessages], up.PhotoId,
CASE
WHEN mr.ReadDate is null then 1 -- New message
ELSE 0 -- Message has been read
END AS NewMessage,
p.LastLoggedIn, p.LoggedIn
FROM [User].[User_Profile] p
JOIN [MailBox].[Message] m on p.Id = m.SenderId
JOIN [MailBox].[MessageRecipient] mr on m.Id = mr.MessageId
LEFT JOIN [User].[User_Photos] up on p.Id = up.UserId
where up.isProfilePic = 1 and mr.RecipientId = #UserId and mr.DeletedDate is null
GROUP BY p.id, p.Username, mr.RecipientId, up.PhotoId, p.LastLoggedIn, p.LoggedIn,
CASE
WHEN mr.ReadDate is null then 1 -- New message
ELSE 0 -- Message has been read
END;
When I execute this I get returned the following:
As you can see its the same user, difference being I have a NewMessage i.e 1 which is causing this user to appear twice, If I remove the case statement within my query then I get the one row but I wouldn't know if I have a new message. I'm having trouble trying to get this query to return only 1 row and state 1 or 0 for NewMessage depending on if I have a new message or not.
Any help would be appreciated.
Following our conversation in the comments I think this will give you the result you are looking for:
Select p.Id [SenderId],
p.Username,
count(mr.RecipientId) [TotalMessages],
count(case when mr.ReadDate is null then 1 end) As [NewMessages],
up.PhotoId,
p.LastLoggedIn,
p.LoggedIn
FROM [User].[User_Profile] p
JOIN [MailBox].[Message] m on p.Id = m.SenderId
JOIN [MailBox].[MessageRecipient] mr on m.Id = mr.MessageId
LEFT JOIN [User].[User_Photos] up on p.Id = up.UserId and up.isProfilePic = 1
where mr.RecipientId = #UserId and mr.DeletedDate is null
GROUP BY p.id,
p.Username,
mr.RecipientId,
up.PhotoId,
p.LastLoggedIn,
p.LoggedIn

Mysql stored procedure query

i have the following stored procedure that returns the sent emails of the latest or last inserted campaigns
"Now my aim to only show the campaigns which have "sent: count greater than "0" how could i make changes to the following sp to do it, because now it is returning all the campaigns including "0" and greater than "0" "..
Code is...
DELIMITER $$
DROP PROCEDURE IF EXISTS `couponcrusaderdev`.`sp_tblemailcampaignLoadTop4`$$
CREATE DEFINER=`anyone`#`000.000.00.00` PROCEDURE `sp_tblemailcampaignLoadTop4`(p_UserID Int(11))
SQL SECURITY INVOKER
BEGIN
SELECT EC.*,(Select MailChimpCampaignID from tblcampaignschedule where EC.CampaignID=tblcampaignschedule.CampaignID ) as MailChimpCampaignID,(Select count(MailChimpCampaignID) from tblcampaignschedule) as msent,CT.CampaignType, (Select tblcampaignschedule.ScheduleDateTime from tblcampaignschedule
where EC.CampaignID=tblcampaignschedule.CampaignID order By ScheduleDateTime desc limit 1) as CampaignDateTime,
(Select Count(*) from tblemailsent ES
inner join tblcampaignschedule CS on CS.CampaignSceduleID= ES.CampaignSceduleID
where ES.Status= 'ProcessedMessage' and CS.CampaignID = EC.CampaignID)as Sent
FROM tblemailcampaign EC
inner join tblcampalgntype CT on CT.CampaignTypeID= EC.CampaignTypeID
inner join tblcompanies C On EC.CompanyID = C.CompanyID
WHERE (p_UserID = 0 OR C.AddUserID = p_UserID)
order by CampaignDateTime desc limit 4
;
END$$
DELIMI
You should use HAVING
HAVING COUNT(sent) >= 0;
Manual:
http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html

MySQL - How to count number of rows from primary query, ignore subquery rows?

I use the following MySQL to return a list of posts and their corresponding comments.
SELECT *
FROM forum_qa
JOIN user_profiles
ON user_id = forum_qa_author_id
LEFT JOIN (SELECT forum_cm_id,
forum_cm_author_id,
forum_qa_id_fk,
forum_cm_text,
FROM forum_cm
JOIN user_profiles
ON user_id = forum_cm_author_id) AS c
ON forum_qa_id = c.forum_qa_id_fk
WHERE forum_qa_parent_id = $forum_qa_id
If I run
$data['num_answers'] = $query->num_rows();
This allows me to get the number of returned rows and pass the array to my controller and view.
But this is returning all rows (posts + comments). So if 1 post has 10 comments, it returns 10.
How could I have this query count only the number of posts (ie, returning 1) not including the subquery?
Each post has a unique id saved in forum_qa.forum_qa_id
Each comment has a unique id saved in forum_cm.forum_cm_id.
Thanks for helping -- will post more code if needed.
Not the fastest, but you are not restricted in using GROUP BY:
SELECT *,
(SELECT COUNT(*) FROM forum_qa WHERE forum_qa_parent_id = $forum_qa_id) Cnt
FROM forum_qa
JOIN user_profiles
ON user_id = forum_qa_author_id
LEFT JOIN (SELECT forum_cm_id,
forum_cm_author_id,
forum_qa_id_fk,
forum_cm_text,
FROM forum_cm
JOIN user_profiles
ON user_id = forum_cm_author_id) AS c
ON forum_qa_id = c.forum_qa_id_fk
WHERE forum_qa_parent_id = $forum_qa_id
You can run another query or add one more column (with an independent subquery) in the result set:
SELECT *
, ( SELECT COUNT(*)
FROM forum_qa
WHERE forum_qa_parent_id = $forum_qa_id
) AS cntPosts
FROM forum_qa
JOIN user_profiles
ON user_id = forum_qa_author_id
LEFT JOIN (SELECT forum_cm_id,
forum_cm_author_id,
forum_qa_id_fk,
forum_cm_text,
FROM forum_cm
JOIN user_profiles
ON user_id = forum_cm_author_id) AS c
ON forum_qa_id = c.forum_qa_id_fk
WHERE forum_qa_parent_id = $forum_qa_id
COUNT(DISTINCT forum_qa.forum_qa_id)
COUNT(DISTINCT col_name) counts the distinct post ids. This should equal the number of posts.

Need help on a stored procedure in SQL Server 2008

I have 4 tables:
Table1
ContentID(pk)
ContentGUID
Description
SiteID
CategoryID
StartDate
DisplayName
ParentId
AssignedAuthors
AssignedEditors
CreatedBy
U.UserName
Created
ModifiedBy
UserName
Modified
Priority
Table2
ContentID(fk)
versionid(pk)
page
Table3
apprhistroyid(pk)
verstionid(fk)
approvalstatusid(fk)
Table4
approvalstatusid(pk)
statusname
I want the total details of table1 and table4. I have tried the following procedure:
ALTER PROCEDURE [dbo].[DEV_SiteAdmin_Menu_GetItem_ALL_TEMP]
#SiteID Int
AS
DECLARE #VersionID int, #ApprovalStatusID int,#StatusName nvarchar(max),#ContentID Int,#Rowcount int
DECLARE #TEMP INT
--set #ApprovalStatusID=5;
--set #StatusName ='New';
set #Rowcount=(select max(ContentID)from dev_content where SiteID=#SiteID)
set #ContentID=(select min(ContentID) from dev_content where SiteID=#SiteID)
SET #TEMP=#ContentID
IF(#Rowcount>=1)
BEGIN
WHILE #Rowcount>1
BEGIN
SET #Rowcount=#Rowcount-1
set #ApprovalStatusID=
CASE
WHEN exists (SELECT VersionID from DEV_ContentVersion WHERE ContentID=#TEMP)
THEN (SELECT ApprovalStatusID FROM DEV_ApprovalStatus WHERE ApprovalStatusID=(SELECT ApprovalStatusID FROM DEV_ApprovalHistory WHERE VersionID=(SELECT VersionID from DEV_ContentVersion WHERE ContentID=(select ContentID from dev_content where ContentID=#ContentID and SiteID=#SiteID)))) else 5 end
set #StatusName=
case
when (#ApprovalStatusID != 5)
then
(SELECT StatusName FROM DEV_ApprovalStatus WHERE ApprovalStatusID=#ApprovalStatusID)
else
'New'
end
SELECT DISTINCT [ContentID]
,[ContentGUID]
,[Description]
,[SiteID]
,[CategoryID]
,[StartDate]
,[DisplayName]
,[ParentId]
,[AssignedAuthors]
,[AssignedEditors]
,[CreatedBy]
,U.UserName 'CreatedUser'
,dbo.fnGetUserNamesFromUserIds([AssignedAuthors],',') 'Authors'
,dbo.fnGetUserNamesFromUserIds([AssignedEditors],',') 'Editors'
,[Created]
,[ModifiedBy]
,U1.UserName 'ModifiedUser'
,[Modified]
,[Priority]
,#ApprovalStatusID [ApprovalStatusID]
,#StatusName [StatusName]
FROM [DEV_Content] C
INNER JOIN dbo.aspnet_Users U ON U.UserId=C.CreatedBy
INNER JOIN dbo.aspnet_Users U1 ON U1.UserId=C.ModifiedBy
WHERE C.SiteID=#SiteID AND [ContentID] = #TEMP
SET #TEMP= #TEMP+1
END
END
else
print 'error'
Where I am getting n no.of rowa that is it returns per 1 contentid 1 row instead I want all return values as one table.
I think your whole query can be boiled down to:
SELECT
[ContentID]
,[ContentGUID]
,[Description]
,[SiteID]
,[CategoryID]
,[StartDate]
,[DisplayName]
,[ParentId]
,[AssignedAuthors]
,[AssignedEditors]
,[CreatedBy]
,U.UserName as CreatedUser
,dbo.fnGetUserNamesFromUserIds([AssignedAuthors],',') as Authors
,dbo.fnGetUserNamesFromUserIds([AssignedEditors],',') as Editors
,[Created]
,[ModifiedBy]
,U1.UserName as ModifiedUser
,[Modified]
,[Priority]
,COALESCE(ah.ApprovalStatusID,5) as ApprovalStatusID
,COALESCE(ast.StatusName,'New' as StatusName
FROM
[DEV_Content] C
INNER JOIN
dbo.aspnet_Users U
ON
U.UserId=C.CreatedBy
INNER JOIN
dbo.aspnet_Users U1
ON
U1.UserId=C.ModifiedBy
left join
DEV_ContentVersion cv
inner join
DEV_ApprovalHistory ah
on
cv.VersionID = ah.VersionID
inner join
DEV_ApprovalStatus ast
on
ah.ApprovalStatusID = ast.ApprovalStatusID
on
C.ContentID = cv.ContentID
WHERE
C.SiteID=#SiteID
But I have to admit, I'm not sure what the DISTINCT was meant to be doing in there.