Why isn't this JOIN working? - mysql

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.

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) ;

sql joining three tables using inner joins

in my database I have 3 tables named items, manufacturers and items_manufacturers. manufacturers has a HAS:MANY relation with items_manufacturers
My items table
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| code | varchar(25) | NO | MUL | NULL | |
| item_category | varchar(100) | NO | | NULL | |
| item_desc | varchar(500) | NO | | NULL | |
| reorder_point | int(11) | NO | | NULL | |
| unit | varchar(45) | NO | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
My manufacturers table
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| code | varchar(25) | NO | | NULL | |
| name | varchar(250) | NO | | NULL | |
| address | varchar(750) | NO | | NULL | |
| contact_no | varchar(50) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
My items_manufacturers table
+-----------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| item_id | bigint(20) | NO | MUL | NULL | |
| manufacturer_id | bigint(20) | NO | MUL | NULL | |
| unit_cost | decimal(20,2) | NO | | NULL | |
| vendor_id | bigint(20) | NO | | NULL | |
+-----------------+---------------+------+-----+---------+----------------+
In my result table I want items_id, items_desc, name of manufacturer from manufacturers table and manufacturer_id. The relation I have is
items.id=items_manufacturers.item_id and
manufacturers.id=items_manufacturers.manufacturer_id.
I tried using inner joins for three tables but not working.
The query I tried
select
items_manufacturers.id,
items.item_desc,
item_manufacturers.manufacturer_id,
manufacturer.name
from items_manufacturers
INNER JOIN items ON items_manufacturers.item_id=items.id
INNER JOIN manufacturers ON items_manufacturers.manufacturer_id=manufacturers.id
Anybody kindly help me with this, I am stuck up from a long time
I used this following code and got the result you were trying to get. This code may solve your problem:
select a.name,b.manufacturer_id,c.id,c.item_desc
from manufacturers as a
inner join
item_manufacturers as b
on b.manufacturer_id=a.id
inner join item as c
on c.id=b.item_id

MySQL JOIN syntax precedence

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

Writing MySQL query with several table joins or multiple select

I am trying to write a MySQL query that gives me results of Organisation Name, its Post Code, any Events that belong to the Organisation and the Post Code of that Event. I've tried all sorts of of join, join and select combinations to no avail. Is this something that is possible ? (I could have a separate table for Org Address and Event Address but it seems like it should be possible to use just one table)
My table structures:
mysql> DESCRIBE cc_organisations;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(10) unsigned | NO | MUL | NULL | |
| type | enum('C','O') | YES | | NULL | |
| name | varchar(150) | NO | MUL | NULL | |
| description | text | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> DESCRIBE cc_events;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| org_id | int(10) unsigned | NO | MUL | NULL | |
| name | varchar(150) | NO | MUL | NULL | |
| start_date | int(11) | NO | MUL | NULL | |
| end_date | int(11) | YES | MUL | NULL | |
| start_time | int(11) | NO | | NULL | |
| end_time | int(11) | NO | | NULL | |
| description | text | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
mysql> DESCRIBE cc_addresses;
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| org_id | int(10) unsigned | YES | MUL | NULL | |
| event_id | int(10) unsigned | YES | MUL | NULL | |
| post_code | varchar(7) | NO | MUL | NULL | |
| address_1 | varchar(100) | NO | | NULL | |
| address_2 | varchar(100) | YES | | NULL | |
| town | varchar(50) | NO | | NULL | |
| county | varchar(50) | NO | | NULL | |
| email | varchar(150) | NO | | NULL | |
| phone | int(11) | YES | | NULL | |
| mobile | int(11) | YES | | NULL | |
| website_uri | varchar(150) | YES | | NULL | |
| facebook_uri | varchar(250) | YES | | NULL | |
| twitter_uri | varchar(250) | YES | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
14 rows in set (0.00 sec)
select o.Name, oAddress.PostCode, e.Name, eAddress.PostCode
from cc_organisations o
inner join cc_addresses oAddress on oAddress.org_id = o.id
left outer join cc_events e on e.org_id=o.id
inner join cc_addresses eAddress on eAddress.event_id = e.id
SELECT cco.name as OrgName, cca.post_code as OrgPostCode, cce.id,
cce.org_id, cce.name, cce.start_date, cce.end_date, cce.start_time,
cce.end_time, cce.description
FROM cc_events cce, cc_addresses cca, cc_organisations cco
WHERE cca.event_id = cce.id AND cco.id=cce.org_id
ORDER BY cce.start_date
LIMIT 50;
You can change your sort and limit, I just added those in because I don't know how big your DB is... You may even be able to get away with:
SELECT cco.name as OrgName, cca.post_code as OrgPostCode, cce.*
FROM cc_events cce, cc_addresses cca, cc_organisations cco
WHERE cca.event_id = cce.id AND cco.id=cce.org_id
ORDER BY cce.start_date LIMIT 50;
But im not 100% sure if the 2nd query will bum out or not.
Your address table has the post codes in it; but it also has an organization id and event id foreign keys. We only need to check the event_id from the address table because any event will belong to an organization.
Address's Event matched Event ID
Event's Organization matched Organization ID