MySQL JOIN syntax precedence - mysql

I have two tables
members
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| mindex | smallint(4) | NO | PRI | NULL | auto_increment |
| memberid | smallint(5) | YES | MUL | NULL | |
| forenames | varchar(40) | YES | | NULL | |
| surname | varchar(20) | YES | | NULL | |
| nameprefix | varchar(30) | YES | | NULL | |
| namesuffix | varchar(50) | YES | | NULL | |
| died | smallint(5) | YES | | NULL | |
| notes | text | YES | | NULL | |
+------------+-------------+------+-----+---------+----------------+
and
memberships;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| mshipindex | smallint(4) | NO | PRI | NULL | auto_increment |
| memberid | smallint(5) | YES | MUL | NULL | |
| msid | smallint(5) | YES | | NULL | |
| mstype | varchar(20) | YES | | NULL | |
| msyear | smallint(5) | YES | | NULL | |
| msposition | varchar(15) | YES | | NULL | |
+------------+-------------+------+-----+---------+----------------+
I want to search on memberships for a year (in memberships.msyear) and get memberships.mstype and members.surname.
I just can't get the right JOIN syntax on this.

You will use something like this:
select m.surname,
s.mstype
from members m
left join memberships s
on m.memberid = s.memberid
where s.msyear = yourYear
See SQL Fiddle with Demo
I used a LEFT JOIN to return the all members, even those who might not have a membership record. If the member does not have a record in the memberships table, then it will return null.
If you need help learning JOIN syntax, here is a great visual explanation of joins

If you just need the syntax Here it is :
Select *
from members m
inner join membership ms on (m.memberid = ms.memberid)
where memberships.msyear = 2012

Related

MySQL Unknown column in where clause?

I have two databases.
One is called INFO with three tables (Stories, Comments, Replies)
Stories has the following fields
+--------------+----------------+------+-----+---------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------------+------+-----+---------------------+-----------------------------+
| storyID | int(11) | NO | PRI | NULL | |
| originalURL | varchar(500) | YES | | NULL | |
| originalDate | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| numDiggs | int(11) | YES | | NULL | |
| numComments | int(11) | YES | | NULL | |
| diggURL | varchar(500) | YES | | NULL | |
| rating | varchar(50) | YES | | NULL | |
| title | varchar(200) | YES | | NULL | |
| summary | varchar(10000) | YES | | NULL | |
| uploaderID | varchar(50) | YES | | NULL | |
| imageURL | varchar(500) | YES | | NULL | |
| category1 | varchar(50) | YES | | NULL | |
| category2 | varchar(50) | YES | | NULL | |
| uploadDate | timestamp | NO | | 0000-00-00 00:00:00 | |
| num | int(11) | YES | | NULL | |
+--------------+----------------+------+-----+---------------------+-----------------------------+
Another database is called Data with one table (User). Fields shown below:
+-------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+---------+-------+
| userID | varchar(50) | NO | PRI | NULL | |
| numStories | int(11) | YES | | NULL | |
| numComments | int(11) | YES | | NULL | |
| numReplies | int(11) | YES | | NULL | |
| numStoryDiggs | int(11) | YES | | NULL | |
| numCommentReplies | int(11) | YES | | NULL | |
| numReplyDiggs | int(11) | YES | | NULL | |
| numStoryComments | int(11) | YES | | NULL | |
| numStoryReplies | int(11) | YES | | NULL | |
+-------------------+-------------+------+-----+---------+-------+
User.userID is full of thousands of unique names. All other fields are currently NULL. The names in User.userID correspond to the names in Stories.uploaderID.
I need to, for each userID in User, count the number of stories uploaded from (i.e. num) Stories for the corresponding name and insert this value into User.numStories.
The query which I have come up with (which produces an error) is:
INSERT INTO DATA.User(numStories)
SELECT count(num)
FROM INFO.Stories
WHERE INFO.Stories.uploaderID=DATA.User.userID;
The error I get when running this query is
Unknown column 'DATA.User.userID' in 'where clause'
Sorry if this is badly explained. I will try and re-explain if need be.
You aren't creating new entries in the User table, you're updating existing ones. Hence, insert isn't the right syntax here, but rather update:
UPDATE DATA.User u
JOIN (SELECT uploaderID, SUM(num) AS sumNum
FROM INFO.Stories
GROUP BY uploadedID) i ON i.uploaderID = u.userID
SET numStories = sumNum
EDIT:
Some clarification, as requested in the comments.
The inner query sums the num in Stories per uploaderId. The updates statement updates the numStories in User the the calculated sum of the inner query of the matching id.

Update MySQL table based on results for joining to tables

I have three tables, emails, person_details and data_providers. Basically all of my users id, email, and current assigned data_providers_id are stored in the emails table.
The second table, person_details contains demographic information collected by multiple data providers, each row identified by an emails_id that is relational to the emails.id data_providers_id that is relational to the third table data_providers.id
The third table, data_providers contains each of my data providers id, name, and precedence.
Basically, a users information could be collected from multiple sources, and I need to UPDATE emails set data_providers_id = based on a select that would JOIN the person_details table and the data_providers table sorting by data_providers.precedence DESC then person_details.import_date ASC and use the first value (highest precedence, then oldest import_date).
I was trying to build the query, but my subquery is returning more than one row. This query is a little over my head, hoping someone more experienced with complex queries might be able to point me in the right direction.
UPDATE emails
SET emails.data_providers_id =
SELECT person_details.data_providers_id
FROM person_details
LEFT JOIN data_providers ON person_details.data_providers_id = data_providers.id
ORDER BY data_providers.percent_payout ASC, person_details.import_date ASC ;
Here are some details about the three tables if this helps. Any guidance would be MUCH appreciated. Thanks in advance :)
emails table:
+-------------------+---------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------------+------+-----+---------------------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| data_providers_id | tinyint(3) unsigned | NO | MUL | NULL | |
| email | varchar(255) | NO | UNI | NULL | |
+-------------------+---------------------+------+-----+---------------------+----------------+
person_details:
+-------------------+---------------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------------+------+-----+---------------------+-------+
| emails_id | int(11) unsigned | NO | PRI | NULL | |
| data_providers_id | tinyint(3) unsigned | NO | PRI | NULL | |
| fname | varchar(255) | YES | | NULL | |
| lname | varchar(255) | YES | | NULL | |
| address_line1 | text | YES | | NULL | |
| address_line2 | text | YES | | NULL | |
| city | varchar(255) | YES | | NULL | |
| state | varchar(2) | YES | | NULL | |
| zip5 | varchar(5) | YES | | NULL | |
| zip4 | varchar(4) | YES | | NULL | |
| home_phone | varchar(10) | YES | | NULL | |
| mobile_phone | varchar(10) | YES | | NULL | |
| work_phone | varchar(10) | YES | | NULL | |
| dob | date | YES | | NULL | |
| gender | varchar(1) | YES | | NULL | |
| ip_address | varchar(15) | NO | | NULL | |
| source | varchar(255) | NO | | NULL | |
| optin_datetime | datetime | NO | MUL | NULL | |
| import_date | timestamp | NO | | 0000-00-00 00:00:00 | |
+-------------------+---------------------+------+-----+---------------------+-------+
data_providers table:
+-----------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+----------------+
| id | tinyint(3) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| precedence | int(2) | YES | | 0 | |
+-----------------+---------------------+------+-----+---------+----------------+
To use a SELECT as an expression you have to put it in parentheses. And to get the first value, use LIMIT 1:
UPDATE emails
SET emails.data_providers_id = (
SELECT person_details.data_providers_id
FROM person_details
LEFT JOIN data_providers ON person_details.data_providers_id = data_providers.id
WHERE person_details.emails_id = emails.id
ORDER BY data_providers.percent_payout ASC, person_details.import_date ASC
LIMIT 1) ;

Two Joins in Mysql Query

Im trying to make a mysql join statement. I want to join the idRestauraunt of Restauraunts and the idRestauraunt of restaurant_categories. My second join i want to join idCategories of Categories and idCategory of restaurant_categories. The query that I'm trying to use is
SELECT distinct r.* from Restaurants r
JOIN restaurant_categories rc on(r.idRestaurant = rc.idRestaurant )
JOIN Categories c on (c.idCategories =rc.idCategories )
WHERE c.Category ='Pizza Hut'
Error Code: 1066. Not unique table/alias: 'Restaurants'
Categories
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| idCategories | int(11) | NO | PRI | NULL | |
| Category | varchar(45) | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
Restaurants
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| idRestaurant | int(11) | NO | PRI | NULL | |
| Name | varchar(45) | YES | | NULL | |
| Password | varchar(45) | YES | | NULL | |
| Email | varchar(45) | YES | | NULL | |
| Number | varchar(45) | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
restaurant_categories
+--------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+-------+
| idCategory | int(11) | YES | MUL | NULL | |
| idRestaurant | int(11) | YES | MUL | NULL | |
+--------------+---------+------+-----+---------+-------+

multi join mysql query taking too long to execute

I have 4 tables as below ,i am trying to join these tables but the query is taking too long to execute.Please tell me how do i optimize this.
Trying to do below
1) using a sub query i am creating a table based on input date range
2) i require to group result based on bank then on district and then on state,so that i can filter results on front end as State-->District-->Bank
3) Also i need to avoid some junk data which i am doing using not like clause.
select substring(a.ifsc,1,4) as code,
s.new_state as state,
s.state_id as stid,
d.new_dist as dist,
b.ifbank as bank,
count(a.amt) as num,
sum(a.amt) as amt from
(SELECT * FROM mtr where orgdate between '$fdate_new' and '$tdate_new')
as a JOIN ifsc b on b.ifscd=a.ifsc
JOIN user c on a.excd=c.mtr
JOIN state_mapping s on b.state=s.org_state
JOIN dist_mapping d on b.dist=d.org_dist
where
s.state_id ='$stid' and
TRIM(d.new_dist) <> '' and
d.new_dist IS NOT NULL
group by bank,dist order by amt desc;
dist_mapping table
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| org_dist | varchar(20) | YES | | NULL | |
| new_dist | varchar(20) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
ifsc table
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| ifscd | varchar(11) | NO | PRI | | |
| ifscbr | varchar(40) | YES | | NULL | |
| ifbank | varchar(40) | YES | | NULL | |
| newifsc | varchar(11) | YES | | NULL | |
| dist | varchar(20) | YES | | NULL | |
| state | varchar(20) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
state_mapping table
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| org_state | varchar(20) | YES | | NULL | |
| new_state | varchar(20) | YES | | NULL | |
| state_id | int(2) | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
user table
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| excode | int(2) | YES | | NULL | |
| mtr | int(2) | YES | | NULL | |
| exname | varchar(40) | YES | | NULL | |
| country | varchar(10) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
mysql> desc mtr;
+---------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------------------+------+-----+---------+-------+
| excd | int(2) | NO | PRI | 0 | |
| orgdate | date | YES | | NULL | |
| amt | double(12,2) | YES | | NULL | |
| obank | int(1) | YES | | NULL | |
| brcd | int(5) | YES | | NULL | |
| brname | varchar(40) | YES | | NULL | |
| rname | varchar(40) | YES | | NULL | |
| bname | varchar(40) | YES | | NULL | |
| baddr | varchar(60) | YES | | NULL | |
| mob | varchar(32) | YES | | NULL | |
| ifsc | varchar(12) | YES | | NULL | |
+---------+---------------------+------+-----+---------+-------+
Subquery takes more time compare to join Please try this
select substring(a.ifsc,1,4) as code,
s.new_state as state,
s.state_id as stid,
d.new_dist as dist,
b.ifbank as bank,
count(a.amt) as num,
sum(a.amt) as amt
From mtr as a
JOIN ifsc b on b.ifscd=a.ifsc and orgdate between '$fdate_new' and '$tdate_new'
JOIN user c on a.excd=c.mtr
JOIN state_mapping s on b.state=s.org_state
JOIN dist_mapping d on b.dist=d.org_dist
where
s.state_id ='$stid' and `enter code here`
TRIM(d.new_dist) <> '' and
d.new_dist IS NOT NULL
group by bank,dist order by amt desc;

Why isn't this JOIN working?

Database Tables
ss_merchant
+----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+----------------+
| pk_merchant_id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(45) | YES | | NULL | |
| website | varchar(100) | YES | | NULL | |
+----------------+--------------+------+-----+---------+----------------+
ss_merchant_store
+----------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+-------------+------+-----+---------+----------------+
| pk_merchant_store_id | bigint(20) | NO | PRI | NULL | auto_increment |
| fk_pk_merchant_id | bigint(20) | YES | | NULL | |
| street | varchar(20) | YES | | NULL | |
| city | varchar(20) | YES | | NULL | |
| postcode | varchar(8) | YES | | NULL | |
| telephone | varchar(15) | YES | | NULL | |
| email | varchar(45) | YES | | NULL | |
+----------------------+-------------+------+-----+---------+----------------+
ss_merchant_store_rating
+-----------------------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------------+------------+------+-----+---------+----------------+
| pk_merchant_store_rating_id | bigint(20) | NO | PRI | NULL | auto_increment |
| fk_pk_merchant_store_id | bigint(20) | NO | | NULL | |
| rating | int(1) | YES | | NULL | |
+-----------------------------+------------+------+-----+---------+----------------+
and my query:
SELECT *
FROM ss_merchant
JOIN ss_merchant_stores
ON ss_merchant.pk_merchant_id = ss_merchant_stores.fk_pk_merchant_id
JOIN ss_merchant_store_rating
ON ss_merchant_stores.pk_merchant_store_id = ss_merchant_store_rating.fk_pk_merchant_store_id
There isn't anything specifically wrong with your join but it does make the assumption that all three tables have at least one row for each merchant_id. If you want to allow for non-existant merchant_store_rating rows consider using a LEFT JOIN
If there is no matching row for the
right table in the ON or USING part in
a LEFT JOIN, a row with all columns
set to NULL is used for the right
table. You can use this fact to find
rows in a table that have no
counterpart in another table:
SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl
ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;
This example finds all rows in
left_tbl with an id value that is not
present in right_tbl (that is, all
rows in left_tbl with no corresponding
row in right_tbl). This assumes that
right_tbl.id is declared NOT NULL.