Fetching data from three tables? - mysql

I have three tables category, brand, product.
Category table -
+---------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| category_name | varchar(255) | NO | | NULL | |
| category_UID | varchar(255) | NO | UNI | NULL | |
| date | date | YES | | NULL | |
| time | time | YES | | NULL | |
| is_delete | tinyint(1) | YES | | 0 | |
+---------------+--------------+------+-----+---------+----------------+
Brand table -
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| brand_name | varchar(255) | NO | | NULL | |
| brand_UID | varchar(255) | NO | UNI | NULL | |
| fk_id | varchar(255) | NO | | NULL | |
| date | date | NO | | NULL | |
| time | time | NO | | NULL | |
| is_delete | tinyint(1) | YES | | 0 | |
+------------+--------------+------+-----+---------+----------------+
Products -
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| category_UID | varchar(255) | NO | | NULL | |
| brand_UID | varchar(255) | NO | | NULL | |
| product_name | varchar(255) | NO | | NULL | |
| product_UID | varchar(255) | NO | UNI | NULL | |
| keyword | varchar(255) | YES | | NULL | |
| photo | varchar(255) | NO | | NULL | |
| photo_thumbnail | varchar(255) | YES | | NULL | |
| date | date | NO | | NULL | |
| time | time | NO | | NULL | |
| is_delete | tinyint(1) | YES | | 0 | |
| visible | tinyint(1) | YES | | 1 | |
+-----------------+--------------+------+-----+---------+----------------+
In HTML page there is a search type input in which user will type atleast three characters to get the serach result from DB.
How will be search technique -
I want to search for products and grab all their data.
The search string will be find by product_name or keywords from product table.
If the search string doesn't found in product table then the search string may be find by category_name or brand_name from category table or brand table respectively. Now If we get our search then the category_UID must be present in product table. (It means we will get our search only when that category UID stored in product table)
I want to get the output as -
If search success, we must get all the column data from product table including two more columns category_name, brand_name from category table and brand table respectively.
Note :
only one attribute category_UID is common in all three tables.
So How can I get the search for product ?
Is this can be solved by JOIN or UNION technique else I have to use procedural way.

In your table, category_UID and product_UID are the foreign keys references, then the following query will work.
select p.id as id,p.category_UID as category_UID,p.brand_UID as brand_UID,
p.product_name as product_name,p.product_UID as product_UID,p.keyword as keyword,
p.photo as photo,p.photo_thumbnail as photo_thumbnail,p.date as date,p.time as time,
p.is_delete as is_delete,p.visible as visible,c.category_name as category_name, b.brand_name as brand_name
FROM product as p
JOIN Brand as b ON p.brand_UID = b.brand_UID
JOIN category as c ON p.category_UID = c.category_UID
where p.product_name like '%<search_str>%' OR
p.keyword like '%<search_str>%' OR
b.brand_name like '%<search_str>%' OR
c.category_name like '%<search_str>%';

Related

Check that all rows in table A have a specific value in table B, including a GROUP BY

I have two tables - students and evidence - and I'm trying to check for a corresponding value in one column in evidence, grouped by another column in evidence for every entry in students
These are what the tables look like:
> desc students;
+------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| firstname | varchar(191) | NO | | NULL | |
| surname | varchar(191) | NO | | NULL | |
| class_id | int(11) | NO | | NULL | |
| dob | datetime | NO | | NULL | |
| enrollment | datetime | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+---------------------+------+-----+---------+----------------+
> desc evidence;
+---------------+------------------------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------------------------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| type | enum('written','image','audio','video','link') | YES | | NULL | |
| mime | varchar(191) | YES | | NULL | |
| path | varchar(191) | YES | | NULL | |
| user_id | int(11) | NO | | NULL | |
| date_recorded | datetime | YES | | NULL | |
| statement_id | int(11) | NO | | NULL | |
| progress | int(11) | NO | | NULL | |
| notes | mediumtext | YES | | NULL | |
| student | int(11) | NO | MUL | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+---------------+------------------------------------------------+------+-----+---------+----------------+
Entries in the evidence table are associated with a student (evidence.student_id) and an evidence statement (evidence.statement_id) and then given a progress value of 1 (in progress) or 2 (complete).
I want to be able to check that for each statement_id every student has at least one row with the progress entry set to 2. Ideally I'd like to GROUP BY statement_id and only return a value of 2 for progress if every student has at least one row in the evidence table for that statement_id where progress has been set to 2.
The goal is to list all of the statement_ids where everyone in a class has completed the task (and therefore had some evidence added with progress set to complete).
I've tried doing joins similar to this
SELECT * FROM students left join evidence ON students.id = evidence.student GROUP BY evidence.statement_id HAVING progress = 2;
but the problem there is that if one student is marked as completing a statement_id but another student doesn't have any entries for that statement_id then progress will return 2. I'd rather it just returned NULL for the student without any entries.
I'm pretty stumped on this one to any help is greatly appreciated.

Don't know how to GROUP_BY my data

Here is a description of my tables
describe book;
+----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| isbn | varchar(20) | NO | PRI | NULL | |
| title | varchar(30) | YES | | NULL | |
| date_published | date | YES | | NULL | |
| publisher_id | int(11) | YES | | NULL | |
+----------------+-------------+------+-----+---------+-------+
describe author;
+------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| author_id | int(11) | NO | PRI | NULL | |
| first_name | varchar(20) | YES | | NULL | |
| last_name | varchar(20) | YES | | NULL | |
+------------+-------------+------+-----+---------+-------+
describe stored_on;
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| isbn | varchar(20) | YES | | NULL | |
| total_copies | int(11) | YES | | NULL | |
| shelf_number | int(11) | YES | | NULL | |
| library | varchar(20) | YES | MUL | NULL | |
+--------------+-------------+------+-----+---------+-------+
describe written_by;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| isbn | varchar(20) | YES | MUL | NULL | |
| author_id | int(11) | YES | MUL | NULL | |
+-----------+-------------+------+-----+---------+-------+
I am trying to display book name, list of authors that wrote that book, shelf number, total copies, and the library the book is located at.
SELECT
b.title,
GROUP_CONCAT(CONCAT_WS(' ',a.first_name, a.last_name )) AS authors,
so.shelf_number,
so.total_copies,
so.library
FROM
stored_on so
LEFT OUTER JOIN book b ON so.isbn = b.isbn
LEFT OUTER JOIN written_by wb ON wb.isbn = so.isbn
LEFT OUTER JOIN author a ON wb.author_id = a.author_id
GROUP BY (b.title);
I don't know how to group my data at the end in a way that will give me duplicate titles/isbn.
Example: There is a book at one library, and the same book at another library, I want to print out the data for each one. They are all listed in my stored_on table to begin with, and I can print out all of the entries when I don't use GROUP_CONCAT, but I do get double entries in the authors field.
Cannot seem to figure this one out.

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