MYSQL multiple joins with reference table - mysql

I have researched tirelessly to try and understand mysql joins with multiple tables and how reference tables come into play but to no avail. Also this is my first post so be gentle if I missed any rules.
Here are my tables:
customers | CREATE TABLE `customers` (
`customer_num` int(11) NOT NULL AUTO_INCREMENT,
`customer_name` varchar(50) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
`state` varchar(50) DEFAULT NULL,
`country` varchar(50) DEFAULT NULL,
PRIMARY KEY (`customer_num`)
orders | CREATE TABLE `orders` (
`order_num` int(11) NOT NULL AUTO_INCREMENT,
`order_date` date DEFAULT NULL,
`shipped_date` date DEFAULT NULL,
`status` varchar(15) DEFAULT NULL,
`comments` text,
`customer_num` int(11) DEFAULT NULL,
PRIMARY KEY (`order_num`)
p_o | CREATE TABLE `p_o` (
`product_num` int(10) unsigned NOT NULL,
`order_num` int(10) unsigned NOT NULL,
KEY `order_num` (`order_num`)
products | CREATE TABLE `products` (
`product_num` int(11) NOT NULL AUTO_INCREMENT,
`year` int(4) unsigned NOT NULL DEFAULT '2014',
`make` varchar(20) NOT NULL,
`model` varchar(20) NOT NULL,
`price` int(6) NOT NULL DEFAULT '0',
PRIMARY KEY (`product_num`)
Customers has a one-many relationship with orders, while orders references to p_o which has both product_num and order_num, and p_o also connects to products.
My goal is to make a query (that is somewhat optimal, not all selects and wheres) that will show all of this information in one table. I created this but cannot get them to show more than just two tables information.
select * from customers t1 join orders t2 on t1.customer_num=t2.customer_num;
That join shows all of the information from orders and customers, and I intend on it being inner join. I've tried all sorts of ways to get them all to join into one but none of them work, and I do believe it's on my end. Also I'm using a module that makes dynamic mysql tables and doesn't support union, but even if you have a solution that uses union I will take it.
Any help you can offer is greatly appreciated, I've been working on this for far too many hours.

I think you should get the information needed using the following:
SELECT
`orders`.`order_num`,
`orders`.`order_date`,
`orders`.`shipped_date`,
`orders`.`status`,
`orders`.`comments`,
`orders`.`customer_num`,
`customers`.`customer_name`,
`customers`.`city`,
`customers`.`state`,
`customers`.`country`,
`products`.`product_num`,
`products`.`year`,
`products`.`make`,
`products`.`model`,
`products`.`price`
FROM
`orders`
inner join `customers`
ON `customers`.`customer_num` = `orders`.`customer_num`
inner join `p_o`
ON `p_o`.`order_num` = `orders`.`order_num`
inner join `products`
ON `products`.`product_num` = `p_o`.`product_num`
I'd like (and I hope) to help you understand the process of multiple join basing on this problem.
The in-words description of this multiple join operation could be like this:
I need to extract detailed information about orders i.e.: order header info, order customer detailed info and products ordered within each of the order numbers.
According to my database structure I can see that every order header from orders table has field with customer number whom the order belongs to, so I want to connect the detailed data from customers table to every order from orders table.
Then I know that I will also need the detailed specification of each product for every specific order.
My DB structure says that I can access product detailed information from products table through "connection" table p_othen I'm connecting p_o to my already-joined set {customers, orders} basing on the order_num column.
Having this information in the result set by now ({customers, orders, p_o}) I only need to connect products table to the p_o table on the product_code key.
In the end I list the columns needed from final result set consisting from four tables {customers, orders, p_o, products}.
I hope it could help you some way.

Related

Mysql count number of result with join

I have 2 tables.
CREATE TABLE $media_table (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`options` longtext DEFAULT NULL,
`order_id` int(11) unsigned DEFAULT NULL,
`player_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`))
CREATE TABLE $category_table (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`category` varchar(300) DEFAULT NULL,
`media_id` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`))
I get id, options, category for rows matching category 'foo','bar'. I also use limit to get only x number of results.
SELECT mt.id, mt.options, ct.category
FROM $media_table as mt
LEFT JOIN $category_table as ct
ON mt.id = ct.media_id
WHERE mt.player_id = %d AND ct.category IN ('foo','bar')
GROUP BY ct.media_id
ORDER BY mt.order_id
LIMIT $limit
This works as intended. But I dont know how to get total number of results?
I tried this but the count is not correct.
SELECT COUNT(mt.id), ct.category
FROM $media_table as mt
LEFT JOIN $category_table as ct
ON mt.id = ct.media_id
WHERE mt.player_id = %d AND ct.category IN ('foo','bar')
GROUP BY ct.media_id
Where I select all results without the limit (in my previous query) the count is correct.
If I had only one table with primary key id I would do this to get count:
SELECT COUNT(id) FROM table
I dont know how to apply the same to my query.
Edit: I found my answer here select count(*) from select
Question 1: Are you looking at the raw results of the query using a tool like phpMyAdmin or MySQL WorkBency or what?
Question 2: Will the ultimate query results be delivered to the client via a web browser or what?
Answer 1: "The SUM() function returns the total sum of a numeric column."
SELECT SUM(column_name) FROM table_name WHERE condition;
Answer Possibility 2: If the results will be delivered in a web browser you should be able to use PHP or some other server side language like MS Active Server Pages to add up he "COUNT" field of each result.
Answer Possibility 3: Alternative 1: Export the results to a CVS file and import into a spreadsheet.
Maybe some of these suggestions will get the wheels turning and help you find the solution you are looking for.

Connecting two tables and having count, distinct, and average of time difference

First, I apologize if my question is not correctly organized.
I am trying to run an SQL Query in Java in order to return all the records of time difference. So to explain more:
I have two tables. Table A has the following structure:
Table `A` (
`interaction_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`job_id` int(11) NOT NULL,
`task_id` varchar(250) NOT NULL,
`task_time` datetime DEFAULT NULL,
`task_assessment` float DEFAULT NULL,
)
Table `B` (
`task_id` varchar(250) NOT NULL,
`task_type` varchar(250) DEFAULT NULL,
`task_weight` float DEFAULT NULL,
`task_due` datetime DEFAULT NULL,
`Job_id` int(11) NOT NULL
)
what I need is to get the count(distinct) from table A -and I do that using the interaction_id
and then get their times -using the task_time for each user and i use "WHERE user_id='" + userId (a java parameter).
After that I want to link Table A with Table B using Job_id
so that I can get the difference date (in hour, so i used SELECT TIMEDIFF(Hour, A(task_time), B(task_due)).
Finally, i need to get Average of the time difference.
I believe its a bit complicated when describing. But, I would appreciate your advanced help!
Thank you very much
This query should gather the results that you are expecting:
select count(*) as countLines,
avg(time_to_sec(timediff(A.task_time, B.task_due)) / 3600)
from A
inner join B on A.job_id = B.job_id
where A.user_id = #userId

MYSQL group products by compatibilty

I have two tables, one is for kits that can contain various sub-products, and another is a list of sub-products that can't be added together in the same kit.
In simplified form:
CREATE TABLE `kits` (
`subProdID` INT(11) NOT NULL DEFAULT '0',
`kitID` VARCHAR(50) NULL DEFAULT NULL,
`kitName` VARCHAR(512) NULL DEFAULT NULL,
PRIMARY KEY (`subProdID`)
);
CREATE TABLE `subProd_incompatible` (
`IncompID` INT(11) NOT NULL DEFAULT '0',
`subProdID` INT(11) NULL DEFAULT NULL,
`subProdIncompID` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`VersaIncompID`)
)
In subProd_incompatible, subProdID and subProdIncompID all exist as subProdIDs in kits.
Right now I use procedural code outside the database to produce a list of kits that all contain products that do not conflict according to the subProd_incompatible table, but I'd like to do it in SQL if at all possible.
What I'd like is to
SELECT `kitID`, `kitName`, GROUP_CONCAT(`subProdID`)
FROM ("a subquery") AS Q
GROUP BY `GroupingCriterion`
"a subquery" should return the columns of kits, along with a generated GroupingCriterion.
Here is an idea. For each kit, get the list of the matches to the incompatible table for each subproduct. Then, aggregate by the kit and incompatible id and see if any have two products. If so, you have incompatible products in the kit:
select k.kitid, i.InCompId
from kits k join
subProd_incompatible i
on k.subProdId in (i.subProdId, i.subProdIncompID)
group by k.kitid, i.InCompId
having count(distinct k.subProdId) = 2;

Best schema design to store and fetch the multiple ids in mysql

This is second time that i can face this kind of issue to retrieve the data.
CREATE TABLE `pm_projects` (
`project_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`project_name` varchar(255) NOT NULL,
`assigned_client` varchar(100) NOT NULL,
`project_detail` longtext NOT NULL,
`creation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`project_status` tinyint(1) NOT NULL,
PRIMARY KEY (`project_id`),
KEY `assigned_client` (`assigned_client`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
On the above table i have a field assigned_client that holds the multiple id's of the clients that are assigned to the project with comma separated(3,4,...).
And i am trying to fetch the result on this table with the Assigned Client's Name(that is on my pm_users table) with JOIN, I tried the following:
SELECT
p.project_id, u.user_name, p.project_name,
p.creation_date, p.project_status
FROM pm_projects p
LEFT JOIN pm_users u ON u.user_id
IN (
'p.assigned_clients'
)
that returns the NULL value of u.user_name field.
Can i have to change my schema, if yes then how?
OR i am trying with wrong Query?
You can use find_in_set for this:
on find_in_set(u.user_id, p.assigned_clients) > 0;
Note that there are no single quotes around p.assigned_clients. This is another error in your query (but even if you replaced it with back quotes, the query still wouldn't work).
However, the problem is your table schema. You should have a separate association table, with one row per user and assigned client.
Trying to store this all in one field will only lead to problems, overly-complicated queries, and performance problems in the future.
I would go with a many to many link approach.
Something like
CREATE TABLE pm_project_client_link(
project_id INT,
client_id INT
)
That would allow you to write the query something like
SELECT
p.project_id,
u.user_name,
p.project_name,
p.creation_date,
p.project_status
FROM pm_projects p INNER JOIN
pm_project_client_link pcl ON p.project_id = pcl.project_id INNER JOIN
pm_users u ON pcl.client_id = user_id

In MySQL, how to "join" three tables

I've seen a good amount of threads on "how to join more than two tables" but none of those threads seem to solve my problem.
I have three tables:
teams, persons and payfiles
teams Table looks like this:
DROP TABLE IF EXISTS `teams`;
CREATE TABLE IF NOT EXISTS `teams` (
`team_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`leader` varchar(32) NOT NULL,
PRIMARY KEY (`team_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=30;`
persons table:
DROP TABLE IF EXISTS `persons`;
CREATE TABLE IF NOT EXISTS `persons` (
`team_id` int(2) DEFAULT '0',
`hash` varchar(32) NOT NULL,
UNIQUE KEY `hash` (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
payfiles table:
DROP TABLE IF EXISTS `payfiles`;
CREATE TABLE IF NOT EXISTS `payfiles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hash` varchar(32) NOT NULL,
`deals_passed` int(2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1298 ;
Tables have much more columns, but I trimmed them for the sake of simplicity.
teams table contains records in the following way:
1,Team 1,afaf7878af78a
The latter is the team leader's unique hash.
The table persons contains all the personal information, and a unique hash,
For instance
John Doe whose hash is afaf7878af78a who also is the leader of Team 1.
The table payfile also has a "hash" column, that table contains all the information needed to compute employees' checks.
The management team want a general vision of how much the company is making. They want to see how much money every single team is bringing in.
The problem I'm facing here, is trying to group the earnings by "teams"
My best try so far is this
SELECT hash, SUM(deals_passed) as deals FROM payfiles JOIN persons ON persons.hash = payfiles.hash GROUP BY payfiles.hash
but I can't see an optimized way to query the database in order to generate a team by team general vision of earnings without changing the structure of the database.
For instance:
John Doe, and Jane Doe belong to "Team 1" and they brought in $500 and $600 respectively.
I want to generate something like:
"Team 1 brought in $1100"
My alternative is to change the structure of the database, and add a new column to the payfile table. Such column would be team_id so I can query it easily, but the database currently has about 10,000 records so that implies updating the 10K records that didn't consider a team_id column, and make a lot of changes to the GUI, something that I don't really want to do, although if that's the easiest and best option I'll do it.
Thanks!
SELECT
teams.name,
SUM(payfiles.deals_passed) AS team_deals_passed
FROM payfiles
LEFT JOIN persons USING (hash)
LEFT JOIN teams USING (team_id)
GROUP BY teams.team_id
You can use SUM() to the get the total, and use GROUP BY for the team to get each total by team.