MySQl Comparison of Two Different Tables
I have two tables with these structures:
Table 1
FullContact
-----------
id
name
phone
address
email
phone
registration
marketingId
created
Table 2
Contacted
-----------
first_name
last_name
email
The FullContact table contains people and the Contacted might contain the same individuals but is given back to me in a strange column structure.
The FullContact might contain duplicates and the Contacted has no duplicates.
Main Goal: I want to see how many from Contacted are in FullContact.
The query I am trying to run is of this form:
SELECT distinct fc.name, fc.email, fc.phone, concat_ws(" ",c.first_name, c.last_name),
c.phone from Contacted c
INNER JOIN FullContact fc
ON ( concat_ws(" ", c.first_name,
c.last_name) = fc.name or c.email = fc.email or (fc.phone REGEXP '[0-9]+$') = c.phone)
and fc.created >= '2011-11-01';
Explanation of Query:
I am trying to select the items in FullContact that are the same as Contacted by using an inner join and constraining by three string parameters and a date parameter.
Problem:
I made the select statement to show the results of items from FullContact and items from Contacted. The results contain FullContact columns being unique and Contact values duplicating.
Is this the correct query to run?
Thanks
You are checking for three lots of duplicates in there, name, email or phone.
So if you have two different names with the same email, you get two records in the result. I would have expected and in the on clause.
Related
So I have a database with two tables, profile, and friends. The primary key in profile is an auto incremented int, and it is a foreign key in friends. The fields in the profile table are: id, name, age, bio, motto, email_address.
The fields in friends is: initiator_id, receiver_id, date_added.
So ultimately I am trying to make a query where I set the initiator_id and get a list of receiver_id's, and use those id numbers to get them from the profile table.
I've tried left join's, inner joins, and joins in general. Open to suggestions, and interpretations on what these types of joins are actually doing.
select friends.receiver_id, profile.name
from profile
inner join friends on friends.initiator_id=1;
I need the fields to return the receiver_id number as well as the corresponding name for that id number.
The specification is a bit unclear. Sample data and expected output would go a longs ways towards illustrating the requirements.
But my guess (and without a specification, its just a guess) is that we are after the resultset returned from this query:
SELECT f.receiver_id
, p.name
FROM friends f
JOIN profile p
ON p.id = f.receiver_id
WHERE f.initiator_id = 1
This question already has an answer here:
How can I use FIND_IN_SET within a JOINED table?
(1 answer)
Closed 5 years ago.
Got 2 tables - contacts and messages:
contact_id | contact_email
1 | some#mail.com
2 | other#mail.com
3 | no#nono.com
message_id | message_recipients
1 | 1,2,3
2 | 3
message_recipients field contains ID(s) of contact(s) message was assigned to. Each message can have one or more IDs assigned, so they are separated by , symbol.
I need to show all contacts, and count of messages are assigned to each contact. Since message_recipients field may contain multiple IDs, I can't run a query like SELECT * FROM contacts, messages WHERE contacts.contact_id=messages.message_recipients because it won't work properly.
If I run SELECT * FROM contacts FULL JOIN messages, it returns many duplicated rows from contacts table. Sure thing, I can run SELECT * FROM contacts FULL JOIN messages GROUP BY contact_id, but this one returns only 1st message from messages table.
I know that in order to count how many messages each contact has assigned to, I will probably need to explode message_recipients field from each row into array and use code like if (in_array($contact_id, $message_recipients_array)) {$total++;} or similar. Now my main concern is how to all I need by writing as simple query as possible.
Fix your table structure. Do not store multiple values in one cell. See Normalization
For now, you can use FIND_IN_SET:
select c.contact_id,
c.contact_email,
count(*) no_of_messages
from messages m
join contacts c on find_in_set(c.contact_id, m.message_recipients) > 0
group by c.contact_id,
c.contact_email
But this will be slow as it can't use any index on the contact_id or message_recipients.
To actually fix the issues, don't include recipient_id in the messages table.
You should have stored single recipient in one row in a separate mapping table with many to many relation with (maybe) the following structure.
messages_recipients (
id int PK,
message_id int FK referring message(message_id),
message_recipient_id int FK referring contacts(contact_id)
)
Then all you had to do was:
select c.contact_id,
c.contact_email,
count(*) no_of_messages
from messages_recipients m
join contacts c on c.contact_id = m.message_recipient_id
group by c.contact_id,
c.contact_email
This query is Sargable and will be faster.
Fix your data structure! Storing ids in strings is a really bad idea. Why?
Numbers should be stored as numbers not strings.
SQL does not offer very good string functions.
Foreign key constraints should be properly expressed.
The query optimizer cannot use indexes or partitions.
SQL has a great method for storing lists: it is called a "table".
Sometimes, we are stuck with other people's really, really bad design decisions. MySQL does offer a method for doing what you want, find_in_set(). This is a hack to get around the short-comings of a bad data layout:
select . . .
from contacts c join
messages m
on find_in_set(c.contact_id, m.message_recipients) > 0
I have two tables users and sellers where user_id and seller_id is different. I want to compare the search query on the first name and the last name of sellers and users and get the results. The two tables have no foreign key associates with it, and on the sellers table its just the seller name. No first name or last name.
SELECT *
FROM users
WHERE first_name LIKE "%'.$search_string.'%"
OR last_name LIKE "%'.$search_string.'%"
that works for the users table.. how to join it with the sellers table?
From the users table I would like to get user_id,first_name,last_name. From the sellers table I would like to get seller_id, seller_name.
I don't quite get what you're trying to accomplish, because you don't mention if there's a joinable field like, for example, transaction id, to relate users and sellers.
If you're searching just any users row or sellers row where the subject matches a search string, you might try with
SELECT 'users' as origin, CONCATENATE('first_name',' ','last_name') as name
FROM users
WHERE (first_name like '%".$search_string."%' OR last_name like '%".$search_string."%')
UNION
SELECT 'sellers' as origin, seller_name as name
FROM sellers
WHERE ( seller_name like '%".$search_string."%')
keep in mind that, if you remove the 'origin' column, the UNION statement will perform an implicit DISTINCT on the resultset. If you need to display dupe results then you should use UNION ALL.
Hey guys sorry to ask but i need help with this query please I've been messing around with different solutions but so far have not been able to solve it myself.
I have 4 tables called customer, figures, notes and lender. They all have a field called reference, which is what I'm using to link them together. Customer is the primary table and there is only one record in the figures table for each customer so i can do:
select * From customer, figures
where customer.reference = figures.reference
However, there may be multiple notes and lender records for each customer. How can I link them to show only one record?
Ideally, there would be a way to display it as:
reference, name, figures, lender 1, lender 2, note 1, note 2, note 3
You can use group_concat():
SELECT customer.reference, customer.name, figures.name,
GROUP_CONCAT(DISTINCT lender.name),
GROUP_CONCAT(DISTINCT notes.name)
FROM customer
JOIN figures ON figures.reference = customer.reference
LEFT JOIN lender ON lender.reference = customer.reference
LEFT JOIN notes ON notes.reference = customer.reference
GROUP BY customer.reference;
Assuming that each of the tables has a field name, you should change it to whatever your columns are.
Complete noob question, so apologies for that.
I have two tables, a members table with an email address and telephone number in it and a second table that will have email addresses and telephone numbers in it with many instances of the members' telephone number or email address. I want to query the second table and list all results corresponding to each member's email address or telephone number.
Thanks very much
Here's a rough query based on the info you supplied:
select members_table.*, joined_tables.*
from members_table,
((select * from second_table
join members_table
on members_table.email_address = second_table.email_address)
union /* or intersect if you don't want dupes */
(select * from second_table
join members_table
on members_table.telephone_number = second_table.telephone_number)
) joined_tables;
At least it should give you an idea on how to go about it.