mysql get records associated directly and indirectly - mysqli

I have 3 tables let's say
manager(id, name) teamleader(id, name, associated)
employee(id,name,code)
In teamleader table associated is foreign key of manager table.
In employee table code is either id of manager or teamleader .
Employee is under manager as well as teamleader.
I want to write a query to find employee which directly under by manager and under teamleader which are associated with that manager.
Please help me to solve my issue.

If i understood you question correctly you can try this:
SELECT
e.id,
e.name,
IF(m1.id IS NULL,m1.id,m2.id) as manager_id
FROM
employee e
LEFT JOIN manager m1
ON m1.id = e.code
LEFT JOIN teamleader t1
ON t1.id = e.code
LEFT JOIN manager m2
ON m2.id = t1.associated
WHERE
(
m1.id IS NOT NULL
OR
(
t1.id IS NOT NULL
AND
m2.id IS NOT NULL
)
)
If you want to put a condition on a specific manager just add at the end :
HAVING manager_id = x
where x is the manager id that you wanted

Related

Postgresql, inner join or subquery or view?

I have the following tables:
user
car
dealer
user_metrics
- user_id (FK) (required)
- dealer_id (FK) (can be null)
- car_id (FK) (can be null)
- saved
- .... other columns
A user can save a car or a dealership, when that happens the user_metrics.saved is set to true and the related car_id or dealership_id is set (car_id and dealership_id are exclusive, only one is set for a row).
I want user A to be able to see all users that have saved the same cars / dealerships.
So, if user A has saved car 1, 2,3 and dealership 5,7, I want to get all users that have saved any of those cars / dealerships.
I thought about inner join on user_metrics, but, I am not sure how to write the entire query that would deliver on this.
What query would allow me to get all users that have saved any of the cars/dealerships a certain user has saved?
If I understand as well maybe the below query solve your problem.
First should find a list of user A has been reserved after that should search which of car or dealer used by another user
with user_saved_data as (
select um.*,
u.name,
...
from user_metrics um
inner join user u
on um.user_id = u.id
where um.saved = true
and u.id = $1 -- User id of user 'A' or any username (Or use other column for create custom condition)
)
select usd.name as current_reserved_user,
u.name as reserved_by_user,
d.*,
c.*
from user_metrics um
inner join user u on um.user_id = u.id
left join user_saved_data usd on usd.dealer_id notnull and usd.dealer_id = um.dealer_id
left join user_saved_data usd on usd.car_id notnull and usd.car_id = um.car_id
left join dealer d on um.dealer_id = d.id
left join car c on um.car_id = c.id

How to find in a many to many relation all the identical values in a column and join the table with other three tables?

I have a many to many relation with three columns, (owner_id,property_id,ownership_perc) and for this table applies (many owners have many properties).
So I would like to find all the owner_id who has many properties (property_id) and connect them with other three tables (Table 1,3,4) in order to get further information for the requested result.
All the tables that I'm using are
Table 1: owner (id_owner,name)
Table 2: owner_property (owner_id,property_id,ownership_perc)
Table 3: property(id_property,building_id)
Table 4: building(id_building,address,region)
So, when I'm trying it like this, the query runs but it returns empty.
SELECT address,region,name
FROM owner_property
JOIN property ON owner_property.property_id = property.id_property
JOIN owner ON owner.id_owner = owner_property.owner_id
JOIN building ON property.building_id=building.id_building
GROUP BY owner_id,address,region,name
HAVING count(owner_id) > 1
ORDER BY owner_id;
Only when I'm trying the code below, it returns the owner_id who has many properties (see image below) but without joining it with the other three tables:
SELECT a.*
FROM owner_property a
JOIN (SELECT owner_id, COUNT(owner_id)
FROM owner_property
GROUP BY owner_id
HAVING COUNT(owner_id)>1) b
ON a.owner_id = b.owner_id
ORDER BY a.owner_id,property_id ASC;
So, is there any suggestion on what I'm doing wrong when I'm joining the tables? Thank you!
This query:
SELECT owner_id
FROM owner_property
GROUP BY owner_id
HAVING COUNT(property_id) > 1
returns all the owner_ids with more than 1 property_ids.
If there is a case of duplicates in the combination of owner_id and property_id then instead of COUNT(property_id) use COUNT(DISTINCT property_id) in the HAVING clause.
So join it to the other tables:
SELECT b.address, b.region, o.name
FROM (
SELECT owner_id
FROM owner_property
GROUP BY owner_id
HAVING COUNT(property_id) > 1
) t
INNER JOIN owner_property op ON op.owner_id = t.owner_id
INNER JOIN property p ON op.property_id = p.id_property
INNER JOIN owner o ON o.id_owner = op.owner_id
INNER JOIN building b ON p.building_id = b.id_building
ORDER BY op.owner_id, op.property_id ASC;
Always qualify the column names with the table name/alias.
You can try to use a correlated subquery that counts the ownerships with EXISTS in the WHERE clause.
SELECT b1.address,
b1.region,
o1.name
FROM owner_property op1
INNER JOIN owner o1
ON o1.id_owner = op1.owner_id
INNER JOIN property p1
ON p1.id_property = op1.property_id
INNER JOIN building b1
ON b1.id_building = p1.building_id
WHERE EXISTS (SELECT ''
FROM owner_property op2
WHERE op2.owner_id = op1.owner_id
HAVING count(*) > 1);

JPA N+1 issue with inheritance

If I am in the situation where I have a n+1 problem I normally use the JPA "join fetch" keyword if it is only one indirection (i. e. select p from Person p join fetch p.address) or if it is more than one indirection I use a JPA provider-proprietary query hint, which is in my case eclipselink (i. e. select p from person with the query hint eclipselink.join-fetch=p.address.city). Thats well explained in the article Java Persistence Performance.
Anyway, lately I stumbled over a datamodel where two entities where subclassed by another one.
I have an Account which owns a Contact. A Contact itself is a abstract superclass which is extended by a Person or a Company. And a Person does have a relationship to a list of Hobbyies.
#Entity
public class Account
{
#OneToOne
private Contact contact;
}
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Contact {}
#Entity
public class Person extends Contact
{
#OneToMany
private List<Hobby> hobbies;
}
#Entity
public class Company extends Contact {}
I need to load a list of Accounts, select a from Account a. I surely ran into the n+1 problem, because of the hobbies. No problem I thought, with the two above mentioned and well probed solutions I can cope with the n+1 problem. But soon I realized that does not work.
select a from Account a join fetch a.contacts does not fetch the hobbies. Nor does select a from Account a with the query hint eclipselink.join-fetch=a.contacts. And select a from Account a with the query hint eclipselink.join-fetch=a.contacts.hobbies throws a
... navigated to a non-existent relationship-Exception.
I also tried to use the JPA treat-function i. e. select a from Account a join fetch treat(a.contact as Person) p join fetch p.hobbies, but that does not fetch the hobbies and only fetches the Persons and not the Companies along.
Does anyone have an idea how to use join fetch or eclipselink query hints to accomplish such a query optimization?
EDIT
In order to answer the comment by Chris.
The #BatchFetch annotation at the hobbies does not have any impact on the query. There is no difference to the queries without it.
Here are the sqls generated by each query with the #BatchFetch annotation
select a from Account a
1 SELECT id, contact_id FROM account
2 SELECT DISTINCT DTYPE FROM contact WHERE (ID = ?)
3 SELECT t0.ID, t0.DTYPE, t1.ID, t1.FOUNDED FROM contact t0, company t1 WHERE ((t0.ID = ?) AND ((t1.ID = t0.ID) AND t0.DTYPE = ?))
4 SELECT DISTINCT DTYPE FROM contact WHERE (ID = ?)
5 SELECT t0.ID, t0.DTYPE, t1.ID, t1.NAME FROM contact t0, person t1 WHERE ((t0.ID = ?) AND ((t1.ID = t0.ID) AND (t0.DTYPE = ?)))
6 SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
... (repetition of lines 2 to 6)
select a from Account a join fetch a.contacts
SELECT t3.ID, t3.contact_id, t0.ID, t0.DTYPE, t1.NAME, t2.ID, t2.FOUNDED FROM contacts t0 LEFT OUTER JOIN person t1 ON (t1.ID = t0.ID) LEFT OUTER JOIN company t2 ON (t2.ID = t0.ID), account t3 WHERE (t0.ID = t3.contact_id)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
...

MYSQL database confusion

So on this question, I'm having trouble.
EMPLOYEE(fname,minit,lname,ssn,birthdate,address,sex,salary,superssn,dno) key:ssn
DEPARTMENT(dname,dnumber,mgrssn,mgrstartdate) key:dnumber
PROJECT(pname,pnumber,plocation,dnum) key:pnumber
Here is what I wrote:
Select e.ssn, e.lname,e.fname,
From employee e,
where e.ssn in
(select s.ssn, s.lname,sfname
from employee s,
where s.superssn = e.ssn, AND s.lnamme='Wallace' s.fname ='Jennifer'
)
But I only got 10 out of 15 points, my professor said my select s.ssn,slname part is wrong, and it must "match my e.ssn". How should I fix this?
A self-join (same table). Alias e is for the worker, alias s is for the supervisor.
select s.ssn, s.lname,s.fname,
From employee s
join employee e
on s.ssn=e.superssn
where e.lname='Wallace' and e.fname ='Jennifer'
your in statement is going to make this query slow. you can refactor it to be a self join like so
select e.ssn, e.lname, e.fname
from employee e
join employee s on s.superssn = e.ssn
where s.lnamme='Wallace' AND s.fname ='Jennifer';
the problem with your in statement is you are making a dependent subquery which checks every row in the employee table with every row in the same table.
to break down the query itself
select s.ssn, s.lname, s.fname -- s is the supervisor
from employee e -- e is jennifer
join employee s on s.superssn = e.ssn -- self join on the supervisors id is equal to the employees id
where e.lnamme='Wallace' AND e.fname ='Jennifer';
Using IN is fine, but with a correlated subquery, EXISTS is the way to go:
Select s.ssn, s.lname, s.fname
From employee s
where exists (select 1
from employee e
where e.superssn = s.ssn AND
e.lname = 'Wallace' AND
e.fname = 'Jennifer'
);
Note:
The s and e are swapped. You want the supervisor information, so it goes in the outer query.
The extraneous commas have been removed.
AND has been added.
Using IN, it looks like:
Select s.ssn, s.lname, s.fname
From employee s
where s.ssn IN (select e.superssn
from employee e
where e.lname = 'Wallace' AND
e.fname = 'Jennifer'
);
Note that the correlation clause is not needed.

MS Access INNER JOIN most recent entry

I'm having some trouble trying to get Microsoft Access 2007 to accept my SQL query but it keeps throwing syntax errors at me that don't help me correct the problem.
I have two tables, let's call them Customers and Orders for ease.
I need some customer details, but also a few details from the most recent order. I currently have a query like this:
SELECT c.ID, c.Name, c.Address, o.ID, o.Date, o.TotalPrice
FROM Customers c
INNER JOIN Orders o
ON c.ID = o.CustomerID
AND o.ID = (SELECT TOP 1 ID FROM Orders WHERE CustomerID = c.ID ORDER BY Date DESC)
To me, it appears valid, but Access keeps throwing 'syntax error's at me and when I hit OK, it selects a piece of the SQL text that doesn't even relate to it.
If I take the extra SELECT clause out it works but is obviously not what I need.
Any ideas?
You cannot use AND in that way in MS Access, change it to WHERE. In addition, you have two reserved words in your column (field) names - Name, Date. These should be enclosed in square brackets when not prefixed by a table name or alias, or better, renamed.
SELECT c.ID, c.Name, c.Address, o.ID, o.Date, o.TotalPrice
FROM Customers c
INNER JOIN Orders o
ON c.ID = o.CustomerID
WHERE o.ID = (
SELECT TOP 1 ID FROM Orders
WHERE CustomerID = c.ID ORDER BY [Date] DESC)
I worked out how to do it in Microsoft Access. You INNER JOIN on a pre-sorted sub-query. That way you don't have to do multiple ON conditions which aren't supported.
SELECT c.ID, c.Name, c.Address, o.OrderNo, o.OrderDate, o.TotalPrice
FROM Customers c
INNER JOIN (SELECT * FROM Orders ORDER BY OrderDate DESC) o
ON c.ID = o.CustomerID
How efficient this is another story, but it works...