Stored Procedure to get the count using 2 tables - sql

I am trying to write a complicated stored procedure for the first time. My goal is to get the count with some condition from 2 tables.
Consider Merchant table and Email table.
Email table saves the Email invitations sent by the Merchant. Merchant table has all the Merchant Info along with Email IDs.
My goal is to get the count of EmailID s that are in the Merchant table by checking if the Email invitations sent by Merchant has signed up.
I have tried to make this question clear... Hope i am clear.
Thanks in advance..

Why a stored procedure? It sounds like it can be done in a single SQL query.
Let's see if I understand your question correctly: Merchants invite other people to become a Merchant as well and you want a list with the number of accepted invitations per merchant?
Something along those lines:
select MerchantName, count(1)
from Merchants, Emails
where Merchants.Id = Emails.Id
and Emails.SignedUp = 'YES!'
group by MerchantName;

It sounds like there is some confusion in that schema you're describing. Based on what I think you're trying to do I'd suggest you have a Merchant table, an Email table and a MerchantEmail table which links Merchants to email invitations sent.
The way it appears otherwise with a Merchant table that has an Email ID is a many-to-one relationship so that several Merchants could be the recipients of an email. In that case the Signed Up flag would appear in the Merchants table and not in the Email table.
CREATE PROCEDURE GetMerchantsSignedUp
#EmailId INT
AS
SELECT COUNT(*) AS MerchantSignedUp
FROM Merchant, Email
WHERE Merchant.EmailId = Email.Id
AND Merchant.SignedUp = 1
AND Email.Id = #EmailId
Please note that there is some redundancy above which suggests that you need not even include the Email table in the query. Here it acts only to indicate a foreign key relationship.

Related

How to have multiple NOT LIKE in SQL

I have two tables in a database. Contacts and Filter
In Contacts, I have ID, Name, and Email as the fields.
in Filter, I have ID and code
My objective is to be able to query the entire table and export a list that has been filtered by items in the Filter table. (basically the same that could be achieved with a grep -i -Ev ) ... Basically I want to filter out gmail or yahoo or others).
So if I do
select distinct email from contacts where email not like '%gmail%'
One level of the filter works.
but if I do,
select distinct email from contacts where email not like '%gmail%' or not like '%yahoo%'
then things start to fail.
Before I start to integrate the nested select code in filter, I cannot get the multiple where field not like X or field1 not like Y working.
Any input is greatly appreciated.
sample data
name email
bob bob#gmail.com
joey joey#cisco.com
desired output
joey#cisco.com
UPDATE: Thank you all for your help. Answer to phase I of the question was to change from OR to AND. :)
Phase II: Instead of having a query that is larger and larger,.. I would rather use a query determine the items to exclude (meaning if any of them match, then exclude them).. so I would then add yahoo gmail protonmail to records in the code field of the filters table.. with that would it be
select distinct email from contacts where email not like in (select code from filters)
This fails as it says that the select has multiple records
UPDATE:
SELECT DISTINCT email FROM Contacts WHERE email NOT LIKE (select filters.code from filters where filters.id=4)
works.. but is only pulling one record as the filter. not all of them as filters.
You just need to use AND instead of OR.
SELECT distinct email
FROM
contacts
WHERE
email not like '%gmail%'
AND email not like '%yahoo%'
You can benefit from CHARINDEX like below, I think this will increase the performance of your query. Also, you can use group by instead of distinct, it will also help the performance.
select email
from contacts
where charindex('gmail',email) < 1
and charindex('yahoo',email) < 1
group by email
Two issue
you need the column name for each condition so add email after the OR
select distinct email from contacts where email not like '%gmail%' or email not like '%yahoo%'
and could be you want check for bot in the same time so you need AND
select distinct email from contacts where email not like '%gmail%' AND email not like '%yahoo%'
As others have noted, the correct boolean connector with NOT LIKE is AND, not OR.
You might see the logic using NOT:
select distinct email
from contacts
where not (email like '%gmail%' or email like '%yahoo%');
If your select has two NOT LIKE criteria connected by an OR condition then everything will meet the criteria. In this situation "gmail" is not like "yahoo" and "yahoo" is not like "gmail" so even those two will pass the criteria. By converting the select to use the AND condition instead you capture those situations. The syntax requires you to provide the field name in both conditions. I feel that this code is easy to read and meets your needs.
SELECT distinct email
FROM contacts
WHERE email not like '%gmail%'
AND email not like '%yahoo%'

Build a Query to get the informations from a specific user

I'm building a Chat with three Tables.
Conversation, Conversation_reply and user
Conversation Columns
id
user_one
user_two
Conversation_reply Columns
id
user_id
conversation.id
reply
User Columns
id
username
I would like to build a list with the name from the users that are chating with a specific user.
Example, my ID is 711, and I am talking with three persons, I would like to get the username from those three persons.
I'm having some issues building this Query because the user_one and user_two are relative, the ID from the receiver sometimes can be inserted as user_one, or user_two. It depends on which user starts chatting first.
How can I build a Query to do that?
Thanks.
Depending on your RDBMS you can check IF/ELSE, CASE/WHEN syntax.
Based on it you write statement:
SELECT if (user_one=711) user_two ELSE user_one
FROM conversation
where user_one=711 OR user_two=711
This is pseudocode, but idea should be clear.

How to tightly contain an SQL query result

I'm writing an application that implements a message system through a 'memos' table in a database. The table has several fields that look like this:
id, date_sent, subject, senderid, recipients,message, status
When someone sends a new memo, it will be entered into the memos table. A memo can be sent to multiple people at the same time and the recipients userid's will be inserted into the 'recipients' field as comma separated values.
It would seem that an SQL query like this would work to see if a specific userid is included in a memo:
SELECT * FROM memos WHERE recipients LIKE %15%
But I'm not sure this is the right solution. If I use the SQL statement above, won't that return everything that "contains" 15? For example, using the above statement, user 15, 1550, 1564, 2015, would all be included in the result set (and those users might not actually be on the recipient list).
What is the best way to resolve this so that ONLY the user 15 is pulled in if they are in the recipient field instead of everything containing a 15? Am I misunderstanding the LIKE statement?
I think you would be better off having your recipients as a child table of the memos table. So your memo's table has a memo ID which is referenced by the child table as
MemoRecipients
-----
MemoRecipientId INT PRIMARY KEY, IDENTITY,
MemoId INT FK to memos NOT NULL
UserId INT NOT NULL
for querying specific memos from a user you would do something like
SELECT *
FROM MEMOS m
INNER JOIN memoRecipients mr on m.Id = mr.memoId
WHERE userId = 15
No, you aren't misunderstood, that's how LIKE works.. But to achieve what you want, it would be better not to combine the recipients into 1 field. Instead try to create separate table that saves the recipient list for each memo..
For me I will use below schema, for your need:
Table_Memo
id, date_sent, subject, senderid, message, status
Table_Recipient
id_memo FK Table_Memo(id), recipient
By doing so, if you want to get specific recipients from a memo, you can do such query:
SELECT a.* FROM Table_Memo a, Table_Recipient b
WHERE a.id = "memo_id" AND a.id = b.id_memo AND b.recipient LIKE %15%
I am not sure how your application is exactly pulling these messages, but I imagine that better way would be creating a table message_recepient, which will represent many-to-many relationship between recipients and memos
id, memoId, recepientId
Then your application could pull messages like this
SELECT m.*
FROM memos m inner join message_recepient mr on m.id = mr.memoId
WHERE recepientId = 15
This way you will get messages for the specific user. Again, don't know what your status field is for but if this is for new/read/unread, you could add in your where
and m.status = 'new'
Order by date_set desc
This way you could just accumulate messages, those that are new

SQL Server Select data excluding Junction table

i need to select data that is not present in the junction table
so got three tables
trialsTable (trialID,TrialName)
VolunteerTAble(volunteerID, VolunteerName)
JunctionTAble(JunctionTableIs,TrialID,VolunteerName)
for every trial an email is sent to volunteers, but next time i want to exclude the volunteers which have received email for that trial and only send email to volunteers which have not received email for that trial, hence i created the junction table which have many to many relationship for the trial and volunteers
Assuming you have a variable or something for the #TrialId which you currently want something like:
SELECT *
FROM VolunteerTable v
WHERE NOT EXISTS(SELECT 1
FROM JunctionTable j
WHERE j.VolunteerName = v.VolunteerName
AND j.TrialID = #TrialId)
And you should probably put volunteerID in you juntion table instead of name.

Database design for email-style application

I'm looking for some advice on how to design a database for an email-style application, specifically how to handle sending a message to multiple users, and displaying what messages were sent to what users.
This is what I have so far:
Messages (Primary Key is Id)
Id (Identity)
SenderId (Foreign Key to Users.Id)
<message data>
ReceivedMessages (Primary key is MessageId + RecipientId)
MessageId (Foreign Key to Messages.Id)
RecipientId (Foreign Key to Users.Id)
IsRead
So for every message sent, there would be one row in Messages, with the data, and then one row for each recipient in ReceivedMessages.
But what if I want to view all the messages sent by a user, and who they were sent to? For each message, I'd need to find all the ReceivedMessages rows for that message, and join all of those with the user table, and then somehow concat all the names (something like this: Concatenate many rows into a single text string?). Might this cause scaling issues, or is it not really anything to worry about?
Any thoughts/suggestions? Thanks.
I see no problem with your design, and would not anticipate and scalability issues with proper indexing on your tables (unless you are talking about massive scale, e.g. gmail, Yahoo mail, etc.).
As far as concatenating the recipient names, I would recommend you do this on the application side and not in SQL, or determine whether you need to do it at all (you might want to show a list and not a concatenated string).
all the messages sent by a user, and who they were sent to
You can do it as an aggregate query, something like:
SELECT u1.user_name, m.message, GROUP_CONCAT(DISTINCT u2.user_name)
FROM messages m JOIN users u1 ON (m.senderID=u1.user_id)
JOIN receivedmessages r ON (m.id=r.messageId)
JOIN users u2 ON (r.RecipientId=u2.user_id)
GROUP BY u1.user_name, m.message;
But because Recipients is essentially unlimited, you may run up against the string length limit on GROUP_CONCAT.
So it's likely better to do an unaggregated select and process the records for display in your application layer:
SELECT u1.user_name, m.message, DISTINCT u2.user_name
FROM messages m JOIN users u1 ON (m.senderID=u1.user_id)
JOIN receivedmessages r ON (m.id=r.messageId)
JOIN users u2 ON (r.RecipientId=u2.user_id)
ORDER BY u1.user_name, m.sent_date, u2.user_name;
Users change name and email, but not their login. Consider mimicking what happens in a unix-based mailbox (e.g. pine) instead:
received_messages (
user_id,
message_id,
message_date,
message_title,
message_content,
message_sender,
message_recipient,
message_is_read
)
and sent_messages along the same lines, i.e. two "files" per user.
Or even merging the latter two with a sent/received flag.
I am facing the same challenge of creating an email or messaging system for a website... You guys forget one thing... IsRead, IsDraft, IsFlagged, IsReply, IsTrash, etc... need to be in a separate table since the same message will be flagged, read or unread by two or more people!! So, we must have a Status table as shown below...
StatusID int
MessageID int
MemberID int
DateTime datetime
IPAddress varchar(65)
IsRead char(1)
IsDraft char(1)
IsFlagged char(1)
IsForwarded char(1)
IsReply char(1)
IsTrash char(1)
You will need at least three tables besides the member or user table:
mail
folders
status
attachment
log
If this is for an existing website... I would separate the mail system into a separate database if you expect this mail system to have a lot of activity.