Two links between 2 tables - mysql

I have 2 tables in my database that I'm trying to design in mysql workbench.
1 table - Company
1. ID
2. Company
3. Company_Number
4. Created_Date
2 table - Employees
1. ID
2. Employee
3. Company_Number
4. Created_Date
I want to create a relationship between Company and Employees. 1 Company can have multiple employees. The problem is that I cannot make Company_Number as a primary key since those keys might duplicate since data will be dumped in daily. Also one employee can work for multiple employees but for each company he/she will have an additional row with data.
Is there a way to make 2 relationships between those two tables? 1 to 1 created_date - created_date & one to many company_number to company_number

Delete Company_Number from Employee table, then create a new table, let's say WorksFor in which you have 2 columns ID_Company,ID_Employee,created_table and make those 2 columns as primary key

A inner join on company_number give you the relation
select c.* e.*
from Company as c
INNER JOIN Employees as e on e.company_number = c.Company_number
and you can create the relation on the two column also
select c.* e.*
from Company as c
INNER JOIN Employees as e on
(e.company_number = c.Company_number and e.Created_Date = c.Created_Date)

Related

Sql to fetch records only if related other table records exist

Table: user
id
compId
1
comp1
2
comp1
Table: Company
id
name
comp1
coke
comp2
pepsi
need a MYSQL query which should fetch company record only if it has one or more users, when passed a company id. I will have other where conditions on company table.
Can this be achieved by joins?
example 1: query(comp1) result: coke (atleast one user exists)
example 2: query(comp2) result: no records (Since no user exists who belong to company comp2)
What you're asking for is called a semi-join. This returns one row from company if there are one or more matching rows in user.
If you use a regular join:
SELECT c.* FROM company c JOIN user u ON u.compid = c.id;
This does return the row from company, but you might not like that it returns one row per user. I.e. rows in the result are multiplied by the number of matches.
There are several possible fixes for this, to reduce the results to one row per company.
SELECT DISTINCT c.* FROM company c JOIN user u ON u.compid = c.id;
SELECT c.* FROM company c JOIN (SELECT DISTINCT compid FROM user) u ON u.compid = c.id;
SELECT * FROM company c WHERE c.id IN (SELECT compid FROM user);
SELECT * FROM company c WHERE EXISTS (SELECT * FROM user WHERE compid = c.id);
Which one is best for your app depends on many factors, such as the sizes of the tables, the other conditions in the query, etc... I'll leave it to you to evaluate them given your specific needs.

How to find out results for not matching particular condition in SQL from multiple tables?

I have 3 tables :
Person table stores basic person wise details with ID as primary Key
This person can have relationships (father / mother etc), which are saved in Relationship table, however the users for them are created in Person table (e.g. ID = 2,3 in person table), This way we know that 2,3 are related to user 1 (carry).
We also have 3rd table - address, which store user ID wise addresses.(for both a user and his related persons, who are also users)
I want to find out if an address exists for either a user or for his related users in SQL. How to achieve this ?
You can combine two rules and search on the combined table as below
SELECT * FROM
(
SELECT username,id,Address.Address
FROM Person
INNER JOIN Address ON Person.id = Address.Userid
UNION ALL
SELECT username,id,Address.Address
FROM Person
INNER JOIN Relationship ON Relationship.Relatedid = Person.id
INNER JOIN Address ON Relationship.Userid = Address.Userid
) as RES
WHERE Address = 'xyz road'
Also you can find DBFiddle link to workout
Query:
select p.id,p.username,(case when a.userid is null then 'No' else 'Yes'end) IsAddressAvailable
from Person p
left join Address a on p.id=a.Userid
Output:
id
username
IsAddressAvailable
1
Carry
Yes
2
Carry-Father
No
3
Carry-Mother
Yes
db<fiddle here

How to get Data from three tables in one query where table 2 contains foreign keys from table 1 and 3

I want to get all the suppliers for one product with product details for which I am using following tables.
I have one Table products with columns
id(pk)
name
type
second table product_supplier with columns
psid(pk)
pid(fk from products)
sid(fk from supplier)
third table supplier with columns
id(pk)
firstname
lastname
I want to get data from these three tables in one mysql query.
Is this what you are looking for?
select p.*, s.*
from products p
inner join product_supplier ps on ps.pid = p.id
inner join supplier s on s.id = ps.sid
order by p.id, s.id
This will return each product along with all the associated suppliers.

MySQL joins and selecting from multiple tables

I am using MySQL Workbench, and I have the following question:
Using the employees data, create select queries that will provide the following information:
Show a list of employees and what department they are in
Columns: Employee Name, Department Name
I have two statements which provide the exact same return, but it's 1000 rows! Am I doing this "join" properly?
SELECT
departments.dept_name, employees.last_name, employees.first_name
FROM
departments, employees
WHERE
departments.dept_name = employees.departments.dept_name;
and
SELECT
dept_name, last_name, first_name
FROM
departments
INNER JOIN
employees
ON
departments.dept_name = employees.departments.dept_name;
Tables employees and departments are always many to many. Therefore, we need input table between them, which has columns id_emp and id_dep or more often 4 column, id_emp, id_dep, from, to. After that, your question is clear and we can speak about.
Example:
Tables:
employees emp_dep departments
id_emp first_name id id_emp id_dep id_dep name
1 John 1 1 1 1 Finacial
2 Elsa 2 2 2 2 Human res
Note: id_emp & id_dep in table emp_dep can't be together primary key beacause every employee can work many times again in same department.
Query on 3 table:
SELECT e.first_name,
d.name
FROM (employees e
INNER JOIN emp_dep ed ON e.id_emp = ed.id_emp)
INNER JOIN departments d ON ed.id_dep = d.id_dep;
Output:
first_name name
John Financial
Elsa Human res
SQL for create this database and table:
CREATE DATABASE employees_dep;
CREATE TABLE employees (id_emp INT AUTO_INCREMENT PRIMARY KEY, first_name VARCHAR(10));
CREATE TABLE departments (id_dep INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(10));
CREATE TABLE emp_dep (id int AUTO_INCREMENT PRIMARY KEY, id_emp INT, id_dep INT);
Both are correct, but the second is better.
Both are same. However second one would be faster given large volume of data, but won't matter on small sized tables.

How to prevent ambiguous name on inner join with two references to same table

I have two tables as follows (in mysql):
Table: invoice
# Column Name
1 Id
2 invoice_date
3 invoice_no
4 consigned_to
5 invoiced_to
6 ...
Table: company
# Column Name
1 Id
2 title
3 ...
Both consigned_to and invoiced_to columns on first table are referencing company.Id.
What I am trying to achieve is a query with following columns
Column Name Table Name
Id (invoice)
invoice_date (invoice)
invoice_no (invoice)
consigned_to (invoice)
consigned_title (company.title)
invoiced_to (invoice)
invoiced_title (company.title)
I need unique column names for the consigned_title and invoiced_title columns, because I should be able to query those columns with titles from company table.
I managed to join single column like this with an alias:
SELECT invoice.*, company.title as consigned_title
from invoice
INNER JOIN company ON invoice.consigned_to = company.Id
but could not managed to reference the same column from company for joining with the invoice.invoiced_to. Is it even possible?
You need table aliases:
SELECT i.*, cc.title as consigned_title, ci.title as invoiced_title
FROM invoice i INNER JOIN
company cc
ON i.consigned_to = cc.Id INNER JOIN
company ci
ON i.invoiced_to = ci.id;
If you rename the id column from the company table for the two use cases then you avoid the need to use range variables (OK, so SQL still forces you to assign range variables -- I'm using c and i in this case -- but you don't need to use them, which is an important distinction):
SELECT invoice_no, consigned_title, invoiced_title
invoice
NATURAL JOIN
( SELECT id AS consigned_to, title AS consigned_title FROM company ) c
NATURAL JOIN
( SELECT id AS invoiced_to, title AS invoiced_title FROM company ) i;