Mysql: get result from 2 tables - mysql

I have 2 tables.
Phonebook:
_________________________________
| id | Photo | Name | Number |
|---------------------------------|
| 1 | abc.jpg | John | 123-45-67 |
|---------------------------------|
| 2 | def.jpg | Sam | 482-34-00 |
|_________________________________|
History:
____________________________________
| id | Name | Date | Type |
|------------------------------------|
| 24 | John | 17.03.2014 | Incoming |
|------------------------------------|
| 25 | Sam | 18.03.2014 | Incoming |
|------------------------------------|
| 26 | Sam | 19.03.2014 | Outgoing |
|____________________________________|
I need to get all columns from History table where id = $id (25 in my case) and get Image column from Phoneboock where History.Name = Phonebook.Name (Sam in my case). Below is the result that I want to get:
______________________________________________
| id | Name | Date | Type | Image |
|----------------------------------------------|
| 25 | Sam | 18.03.2014 | Incoming | def.jpg |
|______________________________________________|

It seems your problem is the SQL to get your data, so use this:
SELECT History.*, Phonebook.Photo
FROM History INNER JOIN Phonebook ON Phonebook.Name = History.Name
AND History.id = $id

You can use JOIN as follows:
SELECT * FROM History INNER JOIN Phonebook WHERE History.name = Phonebook.name
That will give you a join of all the rows. You can customize it more to get what you want. Look at JOIN here for more info

If you are looking for the SQL Select statement, it would look something like this:
SELECT HISTORY.*, PHONEBOOK.Photo FROM HISTORY, PHONEBOOK
WHERE HISTORY.Name = PHONEBOOK.Name AND HISTORY.id='25'

Related

COUNT rows in 3 tables including zero values with MySQL

I have a MySQL 5.6 database with 3 tables:
job_offer
+----+----------+-------------+-----------+
| id | name | position_id | status_id |
+----+----------+-------------+-----------+
| 1 | John | 1 | 4 |
| 2 | Smith | 1 | 4 |
| 3 | Williams | 2 | 2 |
+----+----------+-------------+-----------+
position
+----+----------+
| id | name |
+----+----------+
| 1 | frontend |
| 2 | backend |
+----+----------+
status
+----+-----------+
| id | name |
+----+-----------+
| 1 | contacted |
| 2 | declined |
| 3 | rejected |
| 4 | interview |
+----+-----------+
I would like to build a query that can count all job offers by their position and statuses.
I have this query that performs almost the way I want it:
SELECT
position.name AS position_name,
status.name AS status_name
COUNT(job_offer.id) AS offers
FROM
job_offer
LEFT OUTER JOIN
position
ON job_offer.position_id = position.id
LEFT OUTER JOIN
status
ON job_offer.status_id = status.id
GROUP BY
position_name, status_name
Which gives me this result:
+---------------+-------------+--------+
| position_name | status_name | offers |
+---------------+-------------+--------+
| frontend | interview | 2 |
| backend | declined | 1 |
+---------------+-------------+--------+
The only problem is that I also need to display all existing statuses related to positions regardless of being NULL. So ideally it should look like this:
+---------------+-------------+--------+
| position_name | status_name | offers |
+---------------+-------------+--------+
| frontend | contacted | 0 |
| frontend | declined | 0 |
| frontend | rejected | 0 |
| frontend | interview | 2 |
| backend | contacted | 0 |
| backend | declined | 1 |
| backend | rejected | 0 |
| backend | interview | 0 |
+---------------+-------------+--------+
Is it possible to achieve this with one query? Thanks in advance for any help.
We can use a cross join approach between the position and status table to generate all possible combinations. Then, left join to job_offer and aggregate by position and status to find the counts:
SELECT
p.name AS position_name,
s.name AS status_name,
COUNT(jo.id) AS offers
FROM position p
CROSS JOIN status s
LEFT JOIN job_offer jo
ON jo.position_id = p.id AND
jo.status_id = s.id
GROUP BY
p.name,
s.name
ORDER BY
p.name,
s.name;
Demo

How can i loop through result from mysql query?

I have two tables one for properties and one for users. and I wanna generate a new table that contains propertyID with user name, So i want to loop through the users ids from the properties table then do a query to get the name and assign it to the propertyID like the final table.
Properties
| propertyID | userID |
|------------|--------|
| 123 | 2 |
| 453 | 4 |
| 345 | 6 |
| 378 | 6 |
Users
| userID | name |
|--------|-------|
| 2 | zeyad |
| 4 | test |
| 6 | elan |
Desired Table
| propertyID | name |
|------------|-------|
| 123 | zeyad |
How can i do this?
just like this
CREATE TABLE desiredTable AS
SELECT p.propertyID, u.name FROM Properties p
LEFT JOIN Users u
ON u.userID = p.userID
Careful to the column name you use ("name" is a SQL keyword, use username instead :))

Is it possible to use two COUNT and two JOIN in a SQL query from 3 tables?

So what I'm trying to do here is get a report on how many emails (with a MailChimp like app) were sent by different users, but I want two different metrics in one query. I want to know how many individual emails were sent by each user. Meaning if they sent 3 emails to 100 contacts each, that would display 300. But I also want to know how many unique emails were sent, meaning that would display 3.
I'd like to get something that looks like:
-------------------------------------------------------------
| Full Name | Username | Total Sent | Unique Mails |
|-------------|-----------------|------------|--------------|
| John Doe | jdoe#mail.com | 12000 | 4 |
| James Smith | jsmith#mail.com | 6000 | 12 |
| Jane Jones | jjones#mail.com | 4000 | 2 |
| ... | ... | ... | ... |
-------------------------------------------------------------
So I could know that John sends a few emails to a lot of contacts while James sends more emails to fewer contacts.
Here's what my query looks like. I've changed the table and column names, but this is otherwise an exact representation of what it is.
SELECT
CONCAT(Usernames.FirstName, ' ', Usernames.LastName) AS 'Full Name',
Usernames.Username,
COUNT(Sent_Mail_Contacts.IDContact) AS `Total Sent`,
COUNT(Mass_Mail.IDMass_Mail) AS `Individual E-Mails`
FROM Usernames
LEFT JOIN Sent_Mail_Contacts ON Usernames.Username = Sent_Mail_Contacts.Username
LEFT JOIN Mass_Mail ON Usernames.Username = Mass_Mail.Username
GROUP BY Usernames.Username
ORDER BY `Total Sent`
I have a table with Usernames, a table with individual contacts reached by which emails and a table with unique emails.
So does my query make sense or not? Is this even possible? Because right now when I run it, it gives me something like this:
-------------------------------------------------------------
| Full Name | Username | Total Sent | Unique Mails |
|-------------|-----------------|------------|--------------|
| John Doe | jdoe#mail.com | 12000 | 12000 |
| James Smith | jsmith#mail.com | 6000 | 6000 |
| Jane Jones | jjones#mail.com | 4000 | 4000 |
| ... | ... | ... | ... |
-------------------------------------------------------------
I just gives me the same number in both columns and takes 7 minutes to process.
Here is an example of what the 3 tables would look like separately if that can help:
Usernames
------------------------------------------------
| Username | FirstName | LastName | ... |
|-----------------|-----------|----------|-----|
| jdoe#mail.com | John | Doe | ... |
| jsmith#mail.com | James | Smith | ... |
| jjones#mail.com | Jane | Jones | ... |
| ... | ... | ... | ... |
------------------------------------------------
Mass_Mail
----------------------------------------------------
| ID_Mass_Mail | Username | Date | ... |
|--------------|----------------|------------|-----|
| 1 | jdoe#mail.com | 2019-01-16 | ... |
| 2 | jdoe#mail.com | 2019-01-29 | ... |
| 3 | jjones#mail.com| 2019-02-14 | ... |
| ... | ... | ... | ... |
----------------------------------------------------
Sent_Mail_Contacts
---------------------------------------------------------------------
| ID_Mass_Mail | Username | Contact_ID | Contact_Email | ... |
|--------------|----------------|------------|----------------|------
| 1 | jdoe#mail.com | 1 | bob#mail.com | ... |
| 1 | jdoe#mail.com | 2 | jim#mail.com | ... |
| 1 | jdoe#mail.com | 3 | cindy#mail.com | ... |
| ... | ... | ... | ... | ... |
| 2 | jdoe#mail.com | 4 | mike#mail.com | ... |
| 2 | jdoe#mail.com | 2 | jim#mail.com | ... |
| 2 | jdoe#mail.com | 3 | cindy#mail.com | ... |
| ... | ... | ... | ... | ... |
---------------------------------------------------------------------
Use COUNT(DISTINCT ...) :
SELECT
CONCAT(Usernames.FirstName, ' ', Usernames.LastName) AS 'Full Name',
Usernames.Username,
COUNT(Sent_Mail_Contacts.IDContact) AS `Total Sent`,
COUNT(DISTINCT Mass_Mail.IDMass_Mail) AS `Individual E-Mails`
FROM Usernames
LEFT JOIN Sent_Mail_Contacts ON Usernames.Username = Sent_Mail_Contacts.Username
LEFT JOIN Mass_Mail ON Usernames.Username = Mass_Mail.Username
GROUP BY Usernames.Username
ORDER BY `Total Sent`
NB : this will not make the query any faster though. To start with, you should at least make sure that you are using primary/foreign keys relations in the JOINs : Usernames(Username), Sent_Mail_Contacts(Username), Mass_Mail(Username)
Assuming the values in IDMass_Mail indicate a unique email, then you just need to edit the last COUNT to use the DISTINCT keyword.
COUNT(DISTINCT Mass_Mail.IDMass_Mail) AS `Individual E-Mails`
That will return the number of unique values in the grouping by Username.
You should also get a performance boost if you're able to add indexes to the Username columns in the Sent_Mail_Contacts and Mass_Mail tables.
I managed to do it using a query that (besides from changing the actual table and column names due to privacy concerns) looked exactly like this.
SELECT
Accounts.Account_Name AS `account`,
Usernames.Username AS `username`,
COUNT(Mass_Mail_Reached_Contacts.ID_Contact) AS `total_emails`,
COUNT(Mass_Mail_Reached_Contacts.ID_Mass_Mail) /
(
SELECT COUNT(*)
FROM
Mass_Mail_Reached_Contacts
WHERE
Mass_Mail_Reached_Contacts.DATE >= '2019-02-01'
AND
Mass_Mail_Reached_Contacts.DATE <= '2019-02-28'
)
* 100 AS `%`,
COUNT(DISTINCT Mass_Mail.ID_Mass_Mail) AS `unique_emails`,
COUNT(Mass_Mail_Reached_Contacts.ID_Mass_Mail) /
COUNT(DISTINCT mass_mail.ID_Mass_Mail)
AS `avg_contacts_per_email`
FROM
Usernames
LEFT JOIN Mass_Mail_Reached_Contacts ON Mass_Mail_Reached_Contacts.Username = Usernames.Username
LEFT JOIN Account ON Account.ID_Account = Usernames.ID_Account
LEFT JOIN Mass_Mail ON Mass_Mail.ID_Mass_Mail = Mass_Mail_Reached_Contacts.ID_mass_mail
WHERE
Mass_Mail_Reached_Contacts.DATE >= '2019-02-01'
AND
Mass_Mail_Reached_Contacts.DATE <= '2019-02-28'
GROUP BY
Usernames.Username
HAVING COUNT(DISTINCT Mass_Mail.IDMass_Mail) > 0
ORDER BY
`total_emails` DESC
I'm now able to get a table that looks like this
Emails Stats
--------------------------------------------------------------------------------------
| account | username | total_emails | % | unique_emails | avg_contact_email |
|----------|--------------|--------------|-------|------------------------------------
| Bob inc. | bob#mail.com | 28,550 | 14.52 | 12 | 2379.17 |
| ... | ... | ... | ... | ... | ... |
--------------------------------------------------------------------------------------
To start with: Why do Mass_Mail and Sent_Mail_Contacts both contain a Username? This looks redundant. Or is Sent_Mail_Contacts.ID_Mass_Mail nullable?
For this query at least, I suppose we can ignore the Username in Sent_Mail_Contacts completely. What really links the two tables is the ID_Mass_Mail, and you have forgotten this join criteria in your query.
select
ws_concat(' ', u.firstname, u.lastname) as full_name,
u.username,
count(smc.idmass_mail) as total_sent,
count(mm.idmass_mail) as individual_e_mails
from usernames u
left join mass_mail mm on mm.username = u.username
left join sent_mail_contacts smc on smc.id_mass_mail = u.id_mass_mail
group by u.username
order by total_sent;

Select on row in left with one to many relation

I have table obs
+--------+-------+
| obs_id | name |
+--------+-------|
| 101 | mics |
| 102 | jan |
+--------+-------+
I have table monitoring
+--------+--------+---------+
| mon_id | obs_id | code_id |
+--------+--------+---------+
| 1 | 101 | 201 |
| 2 | 101 | 201 |
| 3 | 101 | 202 |
| 4 | 102 | 201 |
| 5 | 102 | 202 |
+--------+--------+---------+
I have table code
+--------+-----------+
|code_id | code_name |
+--------+-----------|
| 201 | node |
| 202 | java |
| 203 | c++ |
+--------+-----------+
Query result
+--------+--------+---------+-----------+
| obs_id | name | code_id | code_name |
+--------+--------+---------+-----------+
| 101 | mics | 201 | node |
| 102 | jan | 201 | node |
+--------+--------+---------+-----------+
Can someone give me a proper mysql query to come up my result.
select A.obs_id, A.name, M.code_id, C.code_name from obs as A
left join monitoring as M on M.obs_id = A.obs_id
left join code as C on C.code_id = M.code_id
The return of my query is more than 2 or it is not what I want as a result.
As per your result ,its look like you want to results for only 'node' .
Then query will be look like below :
CREATE PROCEDURE GETDATA
AS
#CodeId int=0
BEGIN
select DISTINCT A.obs_id, A.name, M.code_id, C.code_name from obs as A
left join monitoring as M on M.obs_id = A.obs_id
left join code as C on C.code_id = M.code_id WHERE c.code_id=#CodeId
END
Now ,you need to only pass codeID into stored Procedure ,it will be return an output based on CodeID . Its look like dynamic .
The above query will give result as you required.
If you want to get distinct data for all code, then just remove where condition.
Thanks .

Join two table mysql query return all user list values?

Join two table MySQL query return all user list values.
Please correct this query or provide some query.
Table1 : users
+---------+------------+-----------+
| user_id | user_name | cource_id |
+---------+------------+-----------+
| 1 | ramalingam | 1,2,3,4 |
| 2 | yuvi | 1 |
| 3 | Saravanan | 1,2,3 |
| 4 | gandhi | 1 |
+---------+------------+-----------+
Table2 : course
+-----------+-------------+
| cource_id | cource_name |
+-----------+-------------+
| 1 | php |
| 2 | wordpress |
| 3 | seo |
| 4 | magento |
+-----------+-------------+
Output
--------------------------------------
user_id | user_name | cource_id
--------------------------------------
1 | ramalingam| php,wordpress,seo,magnto
2 | yuvi | php
3 | Saravanan | php,wordpress,seo
4 | gandhi | php
This my query
SELECT u.user_id,u.user_name, GROUP_CONCAT(c.cource_name)as course_name
FROM users as u
LEFT JOIN course as c ON c.cource_id = u.user_id
Thank you for any help I can get on this...
In general DB design is bad, don't use comma separated lists at all. Hovewer you should use FIND_IN_SET() in your JOIN clause in order to achieve this:
SELECT
u.user_id,
u.user_name,
GROUP_CONCAT(c.cource_name) AS course_name
FROM
users AS u
LEFT JOIN cource AS c ON FIND_IN_SET(c.cource_id, u.cource_id)
GROUP BY
u.user_id,
u.user_name
Output is:
+---------+------------+---------------------------+
| user_id | user_name | course_name |
+---------+------------+---------------------------+
| 1 | ramalingam | php,wordpress,seo,magento |
| 2 | yuvi | php |
| 3 | Saravanan | php,wordpress,seo |
| 4 | gandhi | php |
+---------+------------+---------------------------+
4 rows in set