MySQL Query Two Table Join - mysql

having a little trouble with this query. I have two tables ...
Account -
ResourceID (int)
AccountID (int) (unique auto-inc)
Resource -
TextName (varchar)
ResourceID (int) (unique auto-inc)
CompanyID (int)
All I have is the AccountID and I Need to make 1 query that will tell me the TextName and ResourceID of all records in the Resource table who have the same CompanyID as the record in the account table that has the same ResourceID and the AccountID that I provide.
Here is what I have so far and already it has narrowed it down to only one entry ... and I have not even begun to try to incorporate the CompanyID yet.
SELECT r.ResId, r.FirstName, r.LastName
FROM account a, resource r
WHERE a.AccId='7' AND a.ResId = r.ResId
Any help is much appreciated. Thanks

You need an auto join to get the similar resource sharing the company !
SELECT rSameCompany.ResId, rSameCompany.FirstName, rSameCompany.LastName
FROM resource r
INNER JOIN resource rSameCompany
ON r.CompanyID = rSameCompany.CompanyID
INNER JOIN account a
ON r.ResourceID = a.ResourceID
AND a.AccId='7'

You want to LEFT JOIN on Account.ResourceID = Resource.ResourceID.

Related

MySql - Slow Query when adding Order by

I've an application which reads email messages (I download the emails from gmail inbox in my application's database) from MySql Database. and the Database has following structure
Table1 (Contacts):
ContactID (int)
ContactName (varchar(100)
ContactEmailAddress (varchar(150))
Table2 (Subjects):
SubjectID (int)
ContactID (int)
Subject (varchar(200))
Table3 (Messages):
MessageID (int)
SubjectID (int)
MessageText (varchar(150)
IsRead (tinyint)
IsReceived (tinyint)
MessageDate (DateTime)
And here is my query to fetch most recent 40 records
SELECT * FROM(SELECT ROW_NUMBER()OVER(Order by isRead ASC,MessageDate DESC) RecID,
c.ContactName,s.subject,s.SubjectID,d.MessageDate,d.isRead
from Contacts c
INNER JOIN Subjects s on s.ContactID=c.ContactID
JOIN (
select MAX(MessageID) dtl_id,SubjectID from Messages where IsReceived=1
GROUP BY SubjectID)d_max on (d_max.subjectid=s.subjectid)
JOIN Messages d on (d.MessageID=d_max.dtl_id)
) AS RowConstrainedResult where RecID >=1 and RecID <=40 ORDER BY RecID
but this query takes almost 15 seconds to load. What should be done to improve the query performance. as my all primary key columns and referenced key columns are indexed. And the Messages table has almost 500k records in it.
The EXPLAIN in the link you provided does not seem to refer to the SELECT you provided, so I have to ignore it.
This index may be helpful:
Messages: (IsReceived, SubjectID, MessageID)
I added the tag [groupwise-maximum]. It links to a lot of other Questions that are doing similar things. Very few actually succeed in optimizing the task. I have a comparison of the faster-than-most techniques here: http://mysql.rjweb.org/doc.php/groupwise_max

SQL: INSERT INTO table(...) VALUES (...) with data retrieved from other tables

Thank you for passing by. I know basic SQL syntax and I can't seem to find a way to accomplish this task.
I need to create a stored procedure which inserts data from one table in another, amid retrieving data from many others. Suppose I have these tables with columns:
users
name (varchar)
sub_id (int)
dub_id (int)
tmp_users
name (varchar)
sub_name (varchar)
dub_name (varchar)
subs
id (int)
name (varchar)
dubs
id (int)
name (varchar)
Translated in pseudocode I should do something like this:
INSERT INTO users (name, sub_id, dub_id)
ALL ROWS FROM tmp_users VALUES (
name = tmp_users.name,
sub_id = SELECT id FROM subs WHERE tmp_users.sub_name = subs.name,
dub_id = SELECT id FROM dubs WHERE tmp_users.dub_name = dubs.name,
)
In wording I need to insert into users all rows from tmp_users, to keep the col tmp_users.name, but retrieve the afferent ids of all other tables based on *_name column. How should I approach this task?
It seems like you are looking for the INSERT ... SELECT syntax:
INSERT INTO users (name, sub_id, dub_id)
SELECT
tu.name,
s.id,
d.id
FROM tmp_users tu
LEFT JOIN subs s ON s.name = tu.sub_name
LEFT JOIN dubs d ON d.name = tu.dub_name
This brings all rows from tmp_users, then attempt to recover the corresponding sub_id and dub_id. For each row returned by the select, a record is inserted in users. A good thing about this syntax is that you can run the select query independently first, to see what would be inserted.

Differences between two result sets MySQL

Very beginner question but haven't been able to come up with answer after reading various help resources.
I have a table group_affiliations which is a joining table between the tables users and groups. Relevant columns: Id, user_id, group_id. I am doing a data cleanup where users were assigned a group_id based on a location which used to be a 3 character abbreviation of a city but has since gone to spelling out full city (ex: a group_id for CHA was previously assigned and now a group_id for Charlotte). Most users currently have both group_ids associated with their user_id but some still only have the old group_id and were never assigned the new one.
What is the most efficient way of finding which ids are in this result set:
select user_id from group_affiliations where group_id=OldId;
and not in this result set:
select user_id from group_affiliations where group_id=NewId;
SELECT 'user_id'
from 'group_affiliations'
where 'group_id' = OldId
and 'group_id' != NewId
how about using a JOIN
SELECT g1.'user_id'
from 'group_affiliations' g1
inner join 'group_affiliations' g2
on g2.'group_id' != NewId
and g2.'group_id' = OldId
and g1.'user_id'=g2.'user_id'

How should I organize this(simple polling system) in my relational database?

My goal is a simple polling system where users can create a poll question, provide the poll with a set of options(answers) and vote on each poll. I'll provide a simple set of fields I need to collect. Then, I'll provide my solution. Could you tell me if my solution is acceptable?
Fields required: questionText, date, (poster)userId, options(answers), response, (responder)userID, responseDate
My curent solution:
Table: Polls
Fields: questionID, questionText, date, userID
Table: Options
Fields: optionID, optionText, questionID
Table: Respnoses
Fields: responseID, optionID, userID, responseDate
So to find if a user has responded to a specific poll, I would have to query like this:
SELECT responseID FROM Responses
WHERE userID = [user's id] AND optionID IN(
Select optionID FROM Options
WHERE questionID = [specific questionID])
Does that query make sense too?
Thanks in advance.
This model looks fine to me, as does the query. I'm a fan of JOINs, so I would have structured your select query more like this (not a recommendation, just a clarifying alternative):
SELECT p.questionText, o.optionText AS selected_answer, r.responseDate, r.userID
FROM Responses r
JOIN Options o ON r.optionID = o.optionID
JOIN Polls p ON o.questionID = p.questionID
WHERE r.userID = [user ID]
My only thought is that, depending on your needs and how auditable you'll want this system to be, you may want extra fields such as timestamps on the Options and Polls tables. (A "date_edited" versus "date_created"? In low-stakes contexts this may not be needed.)

Create Contacts Database Which Refers to Users Without Duplicates

My question is similar (but at the same time completely different) than this question:
Contacts Database
The question is simple: How can I create a Contacts database table which stores a user id and contact id without duplicating keys.
For example, if I have a table called Contacts, it would have a column user_id, and a column contact_id.
Once I do that, it should be as simple as inserting the user and the added contact. Once that is done though, how do I select all of a user's contacts? Also, how do I narrow down the contact entry enough to delete it if need be?
I ended up just creating a table with two foreign keys and then selecting them based on either of the fields.
For example (pseudo code--no specific language, just english):
Table Contact:
user = ForeignKey(from user table)
contact = ForeignKey(from user table)
Then whenever I need something from them, I'll check if the user field contains what I want and then I'll check if the contact field has what I want. This way I don't have to repeat records and I can still find what I need.
Thanks for your answers.
Similar to the question in the link. You would have 3 tables.
Table 1
User_ID
Name
PK(User_ID)
Table 2
Contact_id
Address
Phone_Number
etc...
PK(Contact_id)
Table 3
User_ID
Contact_id
PK(User_ID, Contact_id)
Here you would have ContactID in table 2 as an autoinc column.
Also, when inserting in Table 3, MySQL would throw an error if there is a duplicate.
To select all of a users contacts, use:
SELECT *
FROM Table_2 join Table_3
ON Table_2.Contact_id = Table_3.contact_id
WHERE Table2.User_id = <userid>
Or if you need it for a particular name, then
SELECT *
FROM Table_1 JOIN Table_2
ON Table_1.User_id = Table_2.User_id
JOIN Table_3
ON Table_2.Contact_id = Table_3.contact_id
WHERE Table1.name = <user name>
there are two questions.
" how do I select all of a user's contacts?"
So you have a table tbl_contacts(user_id, contact_id) both them are your primary key, so you won't get duplicated data.
I you want to list all contacts for user_id = ?
SELECT *
FROM tbl_contacts
WHERE user_id = ?
You might want to clarify your second question "Also, how do I narrow down the contact entry enough to delete it if need be?"
You probably have some other properties belong to the user's contact and you will need to use those properties to search for.(eg.: contact_name or contact_number) and when you have 1 record as a result of a query you can -> DELETE FROM tbl_contact WHERE contact_id = ?
If this is not the answer you wanted please clarify your question.