How to fetch record from multiple table in MySQL - php

I normalize my MySQL database which makes me unable to fetch accurate data, actually I need to get detail information about vendors. I have 5 tables. First table is "vendor" in which I have vendor basic info like name, email, address like shown below:
| id | name | email | address |
|------------|------------------|----------------------------------
| 1 | Haris | Haris#gmail.com | Abcd Efgh |
|------------|------------------|----------------------------------
| 2 | John | john#gmail.com | Abcd Efgh |
|------------|------------------|----------------------------------
| 3 | Chris | chris#gmail.com | Abcd Efgh |
Second table "materials" I have a list of materials in which I have two column id and material like shown below:
| id | materials |
|------------|------------------|
| 1 | Iron |
|------------|------------------|
| 2 | Plastic |
|------------|------------------|
| 3 | Steel |
Third Table is "categories" in which I have a list of categories id and categories like shown below:
| id | categories |
|------------|------------------|
| 1 | chair |
|------------|------------------|
| 2 | Table |
|------------|------------------|
| 3 | Glass |
In the fourth table which named "vendors_materials" I have vendor id, vendor name and material code.
| id | name | material_cod |
|------------|------------------|--------------------
| 1 | Haris | 1 |
|------------|------------------|--------------------
| 1 | Haris | 2 |
|------------|------------------|--------------------
| 3 | Chris | 1 |
and In the last fifth table which named "vendors_category" I have vendor id, vendor name and category code.
| id | name | category_cod |
|------------|------------------|--------------------
| 2 | John | 1 |
|------------|------------------|--------------------
| 2 | John | 2 |
|------------|------------------|--------------------
| 1 | Haris | 1 |
I want to get detail of vendor along with materials and categories like shown below:
| id | name | email | address | material | category |
|-----|----------|-------------------|-----------------------------------------
| 1 | Haris | Haris#gmail.com | Abcd Efgh | Iron plastic| Chair
|-----|------------------|-----------------------------------------------------|
| 2 | John | john#gmail.com | Abcd Efgh | | Chair table
|-----|------------------|-----------------------------------------------------|
| 3 | Chris | chris#gmail.com | Abcd Efgh | Iron | |
I have done lot of attempts to achieve my results but failed.

SELECT
vendor.name,
vendor.email,
vendor.address,
materials.materials AS material,
categories.categories AS category
FROM vendor
INNER JOIN vendors_materials ON vendor.name = vendors_category.name
INNER JOIN categories ON vendors_category.category_cod = categories.id
INNER JOIN vendors_materials ON vendors_materials.name = vendor.name
INNER JOIN materials ON materials.id = vendors_materials.material_code
also it is not well normalized database structure, first of all it is not recommended to connect tables with varchar columns when you can to connect with ints. For example your 'connector' tables vendors_materials and vendors_category is connected to vendor by name when you can connect by vendor.id. So your vendors_materials table should look like:
| id | vendor_id | material_cod |
|------------|------------------|--------------------
| 1 | 1 | 1 |
|------------|------------------|--------------------
| 1 | 1 | 2 |
|------------|------------------|--------------------
| 3 | 3 | 1 |
you can do the same in case of vendors_category.

Try following query:
Actually you need to learn use of JOIN in SQL. If you learn this thing then you will be great to make hard queries.
For reference you can go on : SQL Joins
SELECT vendor.name,
vendor.email,
vendor.address,
materials.materials,
categories.categories
FROM vendor
JOIN materials
JOIN categories
JOIN vendors_materials
JOIN vendors_category ON materials.id = materials.material_cod
AND categories.id = vendors_category.material
AND materials.id = vendor.id
AND vendor.id = categories.id
GROUP BY name;

Related

Get SQL results from multiple table based on value in one of the tables

I have a main table (advices) and two reference tables (expert, friend)
advices
----------------------------------------
|id | advisor_id | advisor_type |
----------------------------------------
| 1 | 6 | expert |
| 2 | 6 | friend |
| 3 | 7 | expert |
| 4 | 8 | expert |
----------------------------------------
expert
----------------------------------
|id | lastname | firstname |
----------------------------------
| 6 | Polo | Marco |
| 7 | Wayne | John |
| 8 | Smith | Brad |
----------------------------------
friend
----------------------------------
|id | lastname | firstname |
----------------------------------
| 6 | Doe | John |
| 7 | Brown | Jerry |
| 8 | Goofy | Doofy |
----------------------------------
I would like to get all of the advices (some are from an expert, some are from a friend) and have their respective lastname and firstname be part of the result set.
Each advice row has reference tables (expert, friend tables) tied to it via the id and type.
So I would like to have a result based on id but depending on type inso far as which table to query
The result would look like this
Combining lastname and firstname from reference tables depending on whether it is an expert or a friend.
advices (array)
----------------------------------------------------------------
|id | advisor_id | advisor_type | lastname | firstname |
-----------------------------------------------------------------
| 1 | 6 | expert | Polo | Marco |
| 2 | 6 | friend | Doe | John |
| 3 | 7 | expert | Wayne | John |
| 4 | 8 | expert | Smith | Brown |
-----------------------------------------------------------------
In non programming simple words term I would like to create a query such as this.
SELECT
advices.id, advices.advisor_id, advices.type
IF advices.type==expert THEN expert.lastname, expert.firstname
ELSE IF advices.type==friend THEN friend.lastname, friend.firstname
FROM advices, expert, friend
Obviously I know that the SELECT statement does not allow for this type of on the fly logic. But can this be done in another way?
This should work:
SELECT a.*, e.firstname, e.lastname
FROM advices AS a
INNER JOIN expert AS e ON a.advisor_id = e.id AND a.advisor_type = 'expert'
UNION
SELECT a.*, f.firstname, f.lastname
FROM advices AS a
INNER JOIN friend AS f ON a.advisor_id = f.id AND a.advisor_type = 'friend'

Cross database multiple records with join in MySQL

In this case each person can be assigned to an unlimited number of companies. One of these assigned companies should always be the person's main company. As you can see in the SQL query which I have posted the ID of the person's main organization is stored in the column "main_company_id" in the "person" table.
I have database Internal on server 192.168.0.1 with Person_Company Table as given
+----+-----------+------------+------------+
| id | person_id | company_id | created_at |
+----+-----------+------------+------------+
| 1 | 1005 | 2589 | 00:00:00 |
| 2 | 1006 | 2590 | 00:00:00 |
| 3 | 1007 | 2591 | 00:00:00 |
+----+-----------+------------+------------+
Person Table is as given
+------+-------+---------+-----------------+-----------------+
| id | name | phone | main_company_id | ref_id |
+------+-------+---------+-----------------+-----------------+
| 1005 | John | 0123456 | 2590 | 273722702297768 |
| 1006 | Doe | 7894560 | 2591 | 955413080598021 |
| 1007 | Smith | 9517530 | 2589 | 164283934074454 |
+------+-------+---------+-----------------+-----------------+
Company Table is as given
+------+-----------+---------+-----------------+
| id | name | vat | ref_id |
+------+-----------+---------+-----------------+
| 2589 | Company A | 0123456 | 540603005841231 |
| 2590 | Company B | 7894560 | 725472422399397 |
| 2591 | Company C | 9517530 | 367043795528136 |
+------+-----------+---------+-----------------+
Now there is another database External on the same server 192.168.0.1 with External_Person tables as given:
+----+-----------------+-------+----------------------+--------+
| id | ref_id | name | internal_primary_key | gender |
+----+-----------------+-------+----------------------+--------+
| 1 | 273722702297768 | John | ABC123456 | male |
| 2 | 955413080598021 | Doe | BCD456789 | female |
| 3 | 164283934074454 | Smith | DEF789456 | male |
+----+-----------------+-------+----------------------+--------+
And another table on this External database is External_Company
+----+-----------------+-----------+----------------------+
| id | ref_id | name | internal_primary_key |
+----+-----------------+-----------+----------------------+
| 1 | 540603005841231 | Company A | XX4123456 |
| 2 | 725472422399397 | Company B | XX5456789 |
| 3 | 367043795528136 | Company C | XX6789456 |
+----+-----------------+-----------+----------------------+
What I want to achieve is like this result:
+----+------------+-------------+------------------+
| id | person_key | company_key | main_company_key |
+----+------------+-------------+------------------+
| 1 | ABC123456 | XX4123456 | XX5456789 |
| 2 | BCD456789 | XX5456789 | XX6789456 |
| 3 | DEF789456 | XX6789456 | XX4123456 |
+----+------------+-------------+------------------+
I have already achieved two columns through this statement:
SELECT EEP.internal_primary_key as Person_Key, EEC.internal_primary_key as Company_Key
FROM Internal.Person_Company as IPC
JOIN Internal.Person as IP on IP.id = IPC.person_id
JOIN Internal.Company as IC on IC.id = IPC.company_id
JOIN External.External_Person as EEP on IP.ref_id = EEP.ref_id
JOIN External.External_Company as EEC on IC.ref_id = EEC.ref_id
WHERE IPC.person_id = 1005;
And this has the output like this result:
+----+------------+-------------+
| id | person_key | company_key |
+----+------------+-------------+
| 1 | ABC123456 | XX4123456 |
| 2 | BCD456789 | XX5456789 |
| 3 | DEF789456 | XX6789456 |
+----+------------+-------------+
How can I get the main company's internal_primary_key of the person in this given scenario? How can I amend my this existing query to achieve the desired result which I have mentioned above?
Does this work for you? You have a lot of good work, it seems all you would need is add the EEC.internal_primary_key as main_company_key code to your select statement.
SELECT EEP.internal_primary_key as person_Key, EEC.internal_primary_key as company_Key, EEC.internal_primary_key as main_company_key
FROM Internal.Person_Company as IPC
JOIN Internal.Person as IP on IP.id = IPC.person_id
JOIN Internal.Company as IC on IC.id = IPC.company_id
JOIN External.External_Person as EEP on IP.ref_id = EEP.ref_id
JOIN External.External_Company as EEC on IC.ref_id = EEC.ref_id
WHERE IPC.person_id = 1005;
I have done this successfully after doing some research upon databases
SELECT EEP.internal_primary_key as Person_Key, EEC.internal_primary_key as Company_Key, MEEC.internal_primary_key as Main_Company_Key
FROM Internal.Person_Company as IPC
JOIN Internal.Person as IP on IP.id = IPC.person_id
JOIN Internal.Company as IC on IC.id = IPC.company_id
JOIN External.External_Person as EEP on IP.ref_id = EEP.ref_id
JOIN External.External_Company as EEC on IC.ref_id = EEC.ref_id
JOIN Internal.Company as MIC on MIC.id = IP.main_company_id
JOIN External.External_Company as MEEC on MIC.ref_id = MEEC.ref_id
WHERE IPC.person_id = 1005;
And now this results as I wanted:
+----+------------+-------------+------------------+
| id | person_key | company_key | main_company_key |
+----+------------+-------------+------------------+
| 1 | ABC123456 | XX4123456 | XX5456789 |
| 2 | BCD456789 | XX5456789 | XX6789456 |
| 3 | DEF789456 | XX6789456 | XX4123456 |
+----+------------+-------------+------------------+

Basic SQL query design issue

I'm trying to create a query that would basically be the equivelant of this (does not work).
SELECT * FROM `categories` AS C AND
SELECT * FROM `items` AS I AND
SELECT COUNT(I.id) AS items AND
SELECT SUM(I.price) AS price;
I am not using SQLServer, and I'm using PDO through PHP for database connectivity.
Here's the tables.
Category
+----+------------+
| id | Category |
+----+------------+
| 1 | First_Cat |
| 2 | Second_Cat |
+----+------------+
items
+----+----------+------+-------+
| id | category | name | price |
+----+----------+------+-------+
| 1 | 1 | Foo | 1.99 |
| 2 | 1 | Bar | 2.00 |
| 3 | 2 | ooF | 0.99 |
| 4 | 2 | raB | 1.99 |
+----+----------+------+-------+
Based on these tables I would be expecting these query results:
+----+------------+-------+-------+--+
| id | category | items | price | |
+----+------------+-------+-------+--+
| 1 | First_Cat | 2 | 3.99 | |
| 2 | Second_Cat | 2 | 2.98 | |
+----+------------+-------+-------+--+
Any help?
The query that you have posted in the comment you are not joining the category table and the item table. That makes me think that you could do something like this?:
SELECT
categories.id,
categories.Category,
COUNT(*) AS items,
SUM(items.price) as price
FROM
`categories`
JOIN items
ON categories.id = items.category
GROUP BY
categories.id,
categories.Category

PHP MySQL Join Users Table to Multiple Columns & Rows

I've been having some issues joining tables in a project I'm working on, for projects.
I have 3 tables, one for Projects, one for Customers, and one for Users. I'm trying to store the ID of the Customers and Users in the Projects table, and join them when retrieving.
+----+--------------+
| ID | CustomerName |
+----+--------------+
| 1 | Customer 1 |
| 2 | Customer 2 |
| 3 | Customer 3 |
+----+--------------+
+----+-----------+----------+
| ID | FirstName | LastName |
+----+-----------+----------+
| 1 | Bob | Belcher |
| 2 | Stirling | Archer |
| 3 | Bart | Simpson |
| 4 | Peter | Griffin |
| 5 | BoJack | Horseman |
| 6 | Eric | Cartman |
+----+-----------+----------+
+----+---------------+-----------------+-------------+-------------------+-------------------+--------------------+
| ID | ProjectNumber | ProjectCustomer | ProjectLead | ProjectElectrical | ProjectMechanical | ProjectDescription |
+----+---------------+-----------------+-------------+-------------------+-------------------+--------------------+
| 1 | 0001 | 1 | 3 | 4 | 6 | Project 1 |
| 2 | 0002 | 2 | 2 | 5 | 5 | Project 2 |
| 3 | 0003 | 3 | 1 | 6 | 4 | Project 3 |
+----+---------------+-----------------+-------------+-------------------+-------------------+--------------------+
I've been playing around with Select's all day and this is as far as I've been able to get searching SO:
select Projects.ProjectNumber, Customers.CustomerName, CONCAT_WS(' ', Users.FirstName, Users.LastName) AS ProjectLead, Projects.ProjectElectrical, Projects.ProjectMechanical, Projects.ProjectDescription FROM Projects
INNER JOIN Customers ON Projects.ProjectCustomer = Customers.ID
LEFT JOIN Users ON Projects.ProjectLead = Users.ID
Which gets me part of the way there:
+---------------+--------------+-----------------+-------------------+-------------------+--------------------+
| ProjectNumber | CustomerName | ProjectLead | ProjectElectrical | ProjectMechanical | ProjectDescription |
+---------------+--------------+-----------------+-------------------+-------------------+--------------------+
| 0001 | Customer 1 | Bart Simpson | 4 | 6 | Project 1 |
| 0002 | Customer 2 | Stirling Archer | 5 | 5 | Project 2 |
| 0003 | Customer 3 | Bob Belcher | 6 | 4 | Project 3 |
+---------------+--------------+-----------------+-------------------+-------------------+--------------------+
But for the life of me, I can't get ProjectElectrical and ProjectMechanical to do the same thing as ProjectLead. I either get duplicates of ProjectLead, or I get NULLs.
Can anyone help point me in the right direction? Do I need to completely redesign my query or am I on the right track?
I've fiddle'd it at SQL Fiddle
Thanks in advance for any and all replies!
Here is the updated query from the fiddle:
select Projects.ProjectNumber, Customers.CustomerName, CONCAT_WS(' ', Users.FirstName, Users.LastName) AS ProjectLead, CONCAT_WS(' ', u2.FirstName, u2.LastName) AS ProjectElectrical, CONCAT_WS(' ', u3.FirstName, u3.LastName) AS ProjectMechanical, Projects.ProjectDescription FROM Projects
INNER JOIN Customers ON Projects.ProjectCustomer = Customers.ID
LEFT JOIN Users ON Projects.ProjectLead = Users.ID
LEFT JOIN Users AS u2 ON Projects.ProjectElectrical = u2.ID
LEFT JOIN Users AS u3 ON Projects.ProjectMechanical = u3.ID

Order data within group by that has 2 different columns in MySQL

I am working with a discussion board where there will be a certain topic and the user can comment or upvote another comment. Each comment can also be replied by another user and will recieve notifications.
My notification table
notification_id is the user_id of the logged in user that will receive the notification
notification_from is the user_id of the one who commented or like the users post.
notification_topic is the id of the topic plus the type of notification that will distinguish if it is a comment or an upvote
notification_comment is the comment_id in the topic
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
| notification_id | notification_pic | notification_name | notification_title | notification_user_id | notification_date | notification_from | notification_topic | notification_comment | type | status |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
| 1 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188338 | 32 | 83_upvote | 1 | upvote | read |
| 2 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188342 | 32 | 83_comment | 1 | comment | read |
| 3 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 2 | 1380188505 | 93 | 83_upvote | 1 | upvote | read |
| 4 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 2 | 1380188509 | 93 | 83_comment | 1 | comment | read |
| 5 | 93_1379990163_thumb.jpg | vhon samson | Chrysler files papers for share sale | 0 | 1380246975 | 93 | 83_comment | 1 | comment | unread |
| 6 | 93_1379990163_thumb.jpg | vhon samson | Toyota and Nissan in vehicle recall | 2 | 1380247149 | 93 | 225_comment | 3 | comment | read |
| 7 | default.gif | kath aguilar | Chrysler files papers for share sale | 2 | 1380253584 | 7 | 83_comment | 1 | comment | read |
| 8 | default.gif | kath aguilar | Chrysler files papers for share sale | 93 | 1380253870 | 7 | 83_comment | 2 | comment | unread |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+
My query
This is how I query and group my table:
SELECT *, COUNT(notification_topic) AS topic_count
FROM tbl_notification
WHERE notification_user_id = '{$_SESSION['id']}'
GROUP BY notification_topic
ORDER BY notification_date DESC
LIMIT 8
This is the result of the query:
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
| notification_id | notification_pic | notification_name | notification_title | notification_user_id | notification_date | notification_from | notification_topic | notification_comment | type | status | topic_count |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
| 6 | 93_1379990163_thumb.jpg | vhon samson | Toyota and Nissan in vehicle recall | 2 | 1380247149 | 93 | 225_comment | 3 | comment | read | 1 |
| 2 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188342 | 32 | 83_comment | 1 | comment | read | 3 |
| 1 | 32_1380182434_thumb.jpg | Sheena Salazar | Chrysler files papers for share sale | 2 | 1380188338 | 32 | 83_upvote | 1 | upvote | read | 2 |
+-----------------+-------------------------+-------------------+--------------------------------------+----------------------+-------------------+-------------------+--------------------+----------------------+---------+--------+-------------+
See it on sqlfiddle.
What I need
I need to get the count so that I can come up with a notification like on facebook, like this:
My main problem is I can't ORDER it by notification_date before the GROUP BY because I need to isolate each notification_comment by its notification_topic. I want the latest user that commented or like each topic to be displayed. How will I do this?
If I've understood your problem correctly then you want the groupwise maximum, which can be obtained by selecting the identifying criteria in the group and then joining back to your table:
SELECT *
FROM tbl_notification NATURAL JOIN (
SELECT notification_topic,
notification_user_id,
MAX(notification_date) AS notification_date,
COUNT(*) AS topic_count
FROM tbl_notification
WHERE notification_user_id = 2
GROUP BY notification_topic,
notification_user_id
) AS t
ORDER BY notification_date DESC
LIMIT 8
See it on sqlfiddle.

Categories