How to select entries WITHOUT matching dependents in same table - mysql

What I have is a table containing people. Some people are primary entries and others are secondary (partners, children etc)
The primary entries have a 'cls' of say 3 (where cls is a column name). The secondary entries have different cls, say 4. The secondary entries also have a 'primary' field linking them back to the unique ID of their primary person. (primary field is empty on primary people)
What I want to do is select all primary entries that do not have anyone linking back to them.
Here's where I got to, but it is obviously not right. I figure there is some other form of JOIN that I need? (pp1 is referring to secondaries and pp2 is referring to primaries)
SELECT pp2.per_ID
FROM person pp1 LEFT OUTER JOIN person pp2 ON pp1.primary = pp2.per_ID
WHERE pp1.cls = 4 AND pp2.cls =3
AND pp2.primary IS NULL;
.
TABLE person
COLUMN per_ID, cls, primary

SELECT p.* FROM person as p
LEFT JOIN person AS s
ON p.`primary` = s.per_ID
WHERE s.per_ID IS NULL AND p.cls =3

Related

How to select entries in a join table based on the aggregate selection of data from several other tables?

I have an application based on 4 MySQL tables:
persons
------------
id -- Primary key, unique
name
entity_id -- foreign key => entities
entities
------------
id -- Primary key, unique
name
company_id -- foreign key => companies
companies
------------
id -- Primary key, unique
name
persons_linked_companies -- join table : persons <=> companies
--------------------------
id -- Primary key, unique
persons_id -- foreign key => persons
companies_id -- foreign key => companies
Each "person" belong to an "entity"
Each "entity" belong to a "company"
A "person" can only have one "entity"
An "entity" can only have one "company"
A "person" can be linked to one or more third parties (meaning other companies). For this there is a join table called "persons_linked_companies"
A person can have multiple linked companies, but a person shouldn't be linked to his own company
I can't figure out what kind of subquery/join I should issue to get the following data:
I need to select entries in the join table "persons_linked_companies" to get all persons whose linked company is the same has the company they belong to (because of bullet point 6).
Pseudo code below:
select id from persons_linked_companies where companies_id = (select id from companies where persons.entity.company_id = persons_linked_companies.companies_id)
Besides using aliases. you can join all tables
But this would only yield a result, if you entered such a row in the table persons_linked_companies, which should be not be done by your rule 6
SELECT
id
FROM
persons_linked_companies pcl
WHERE
companies_id = (SELECT
c.id
FROM
companies c
INNER JOIN entities e ON e.company_id = c.id
INNER JOIN persons p ON p.entity_id = e.id
WHERE
p.id = pcl.persons_id)

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

Selecting values from foreign tables

I'm working on the SELECT clause for the VALUES section of an SQL INSERT statement. One of the fields of the record is a foreign key to a table of foreign keys to other records.
Given:
Table - Ing_Fundamental
+----------------+-------------------+
| ID_Fundamental | ID_Title_Category |
+----------------+-------------------+
Table - Title_Category
+-------------------+----------+-------------+
| ID_Title_Category | ID_Title | ID_Category |
+-------------------+----------+-------------+
Table - Titles
+----------+-------+
| ID_Title | Title |
+----------+-------+
Table - Categories
+-------------+----------+
| ID_Category | Category |
+-------------+----------+
I want to select the ID_Title_Category field where Titles.Title = "Hamburger" and Categories.Category = "Meat".
My SQL INSERT statement:
INSERT INTO Ing_Fundamental
(
Ing_Fundamental.ID_Title_Category
)
VALUES
(
(SELECT ????)
)
Here's the SQL CREATE TABLE statement for Ing_Fundamental:
CREATE TABLE IF NOT EXISTS Ing_Fundamental
(
ID_Fundamental INTEGER UNSIGNED PRIMARY KEY AUTO_INCREMENT NOT NULL,
ID_Title_Category INTEGER UNSIGNED,
FOREIGN KEY fk_ID_Title_Category(ID_Title_Category)
REFERENCES ing_title_categories(ID_Title_Category)
ON UPDATE CASCADE
ON DELETE RESTRICT,
UNIQUE(ID_Title_Category)
)
My attempt at the SELECT statement is:
(SELECT Ing_Title_Categories.ID_Title_Category
FROM Ing_Title_Categories
WHERE (ID_Title_Category = 0))
But the above statement isn't going to work correctly because the ID_Title_Category field value is not correct, it must be determined by looking up values in the Titles and Categories tables.
So, what is the SQL syntax for selecting the ID_Title_Category field based on the fields in the Titles and Categories tables?
Edit 1: background / design
A fundamental ingredient has a unique ID.
A fundamental ingredient has a title and a category.
Categories are fixed (limited).
A User wants to search the database for an ingredient based on a title and a category.
A recipe contains one or more ingredients (ingredient IDs).
I don't remember my justification for the Title_Category table; It could either be normalization or reduce the need for a compound primary key.
I'm writing an application in C++ to interact with the database via SQL statements and queries.
In programming terminology:
The Ing_Fundamental record contains a Title_Category record.
The Title_Category record contains a Title record and a Category record.
All records contain an ID field and one or more data fields (such as text).
I want to select the ID_Title_Category field where Titles.Title = "Hamburger" and Categories.Category = "Meat".
That doesn't make sense. Presumably you mean something like you want select ID_Title_Category from Title_Category wherecondition. But what is condition? What are rows Titles and Categories? You don't need to know more SQL to say that.
You might mean that you want select ID_Title_Category from Title_Category rows where row (ID_Title) is in select ID_Table from Titles where Title = 'Hamburger' and where row (ID_Category) is in select ID_Category from Categories where Category = 'Meat'.
Then it is helpful to know that SQL lets you write (...) in (subselect).
select ID_Title_Category
from Title_Category
where (ID_Title) in (select ID_Title from Titles where Title = 'Hamburger')
and (ID_Category) in (select ID_Category from Categories where Category = 'Meat')
Or you might mean that you want select ID_Title_Category from Title_Category rows TC (say) where there exist values for T.ID_Title & C.ID_Category where row T (say) is in Titles and TC.ID_Title = T.ID_Title and T.Title = 'Hamburger' and row C (say) is in Categories and TC.ID_Category = C.ID_Category and C.Category = 'Meat'.
Then it is good to know that in SQL T cross join U is rows (T.X,...,U.Y,...) where row (T.X,...) is in T and row (U.Y,...) is in U. (, is cross join binding looser than the various joins.)
select TC.ID_Title_Category
from Title_Category TC
cross join Titles T
cross join Categories C
where TC.ID_Title = T.ID_Title and T.Title = 'Hamburger'
and TC.ID_Category = C.ID_Category and C.Category = 'Meat'
Also, T cross join U and condition can be expressed as T join U oncondition.
select TC.ID_Title_Category
from Title_Category TC
join Titles T
on TC.ID_Title = T.ID_Title and T.Title = 'Hamburger'
join Categories C
on TC.ID_Category = C.ID_Category and C.Category = 'Meat'
You could write another version knowing that in SQL there exists a row in subselect when EXISTS(subselect).
We don't need to know constraints (PK, UNIQUE, FK, etc) to query. We do need to what each base table row says about the situation. Then we can express what rows are in the result via what rows are in base tables. To use relation operators we need to know how to translate between predicate expressions & relation expressions. We can also describe the rows in the result via what each result row says about the situation. (Which is how you would justify intuitive use of in.) Is there any rule of thumb to construct SQL query from a human-readable description?

How to display information from a referencing table?

There is probably a very simple solution to this, but I couldn't figure out an appropriate way to google it.
I have three tables in my database.
The first one is "customer" and it has (ID, Name, Username etc)
The second one is "attraction" and it has (AttractionID, Name, Location, etc..)
The tird one "favourites" is made in order for the user to save favourites from the second table with the user ID from the first one:
Here is the third table:
CREATE TABLE Favorites (
FavID INT NOT NULL,
ID INT NOT NULL,
AttractionID INT NOT NULL,
PRIMARY KEY (FavID),
FOREIGN KEY (ID) REFERENCES customer(ID),
FOREIGN KEY (AttractionID) REFERENCES attraction(AttractionID)
);
I can insert into the table but what sql query do I need to use in order to show information from the referencing tables?
Lets say the user has saved their user ID and favourite attraction ID to the favourite table, how can I display the name and location from the attraction table that corespond to the foreign key attractionID saved in the favourites table?
Thanks
You should use JOIN for it:
SELECT * FROM Favorites f
INNER JOIN Attraction a ON f.AttractionId = a.AttractionId
INNER JOIN customer c ON f.Id = c.id
f, a and c are just aliases to make the referencing simpler, you could also write
SELECT * FROM Favorites
INNER JOIN Attraction ON Favorites.AttractionId = Attraction.AttractionId
INNER JOIN customer ON Favorites.Id = customer.id
or with AS, which makes it a bit more clear (but longer, so I prefer the first way)
SELECT * FROM Favorites AS f
INNER JOIN Attraction AS a ON f.AttractionId = a.AttractionId
INNER JOIN customer AS c ON f.Id = c.id

ForeignKey Referencing Same Table

There was an interview test in which below was the table and structure
Table Person = id, name, dob, dod, mother_id, father_id
Primary Key (id)
Foreign Key mother_id references Person
Foreign Key father_id references Person
and it was asked
"select all who are mothers"
"select those child who are children of 'John Smith' and 'Jane'
and I was puzzled because I was assuming that foreign key would be linked with some other table as usual. But at that point I failed. do some one know the actual answer and reason?
This kind of data structure is called a "Self Referencing Table"
SELECT DISTINCT mothers.*
FROM person
inner join person mothers on person.mother_id = mothers.id
and
SELECT person.*
FROM person
inner join person fathers on person.father_id = fathers.id
inner join person mothers on person.mother_id = mothers.id
WHERE
fathers.name='john smith'
and
mothers.name='jane'
You can always have foreign key that link to the same table.. There is not problem in that..
See, suppose you are storing a person record in the table, now that person would be having mother and father. And mother and father both are themselves a person.. so, they are itself a record of the same table..
Suppose you have following two records in Person table: -
id name age mother_id
1 xyz 24 5
5 abc 57 6
So, from the above table you see that, person with id = 5 is actually mother of person with id = 1.. So, it is a foreign key referencing the same table..
So, here rather than performing a join operation with a different table, you have to perform join with the same table..
SELECT p2.id FROM
Person p1 join Person p2
WHERE p1.mother_id = p2.id
This query will select the record of mother of your current record..
I was assuming that foreign key would be linked with some other table
as usual.
It still is - it references other records in the same Person table.
-- All Mothers
SELECT mom.name
FROM Person mom
WHERE EXISTS (SELECT 1 FROM Person WHERE mother_id = mom.id);
-- Children of John Smith and Jane
SELECT kid.name
FROM Person kid
INNER JOIN Person mom on kid.mother_id = mom.id
INNER JOIN Person dad on kid.father_id = dad.id
WHERE mom.name = 'Jane' AND
dad.name = 'John Smith';
Have a look at this SQL fiddle here
SELECT *
FROM Person
WHERE father_id = (SELECT id FROM Person WHERE name = 'John Smith')
AND mother_id = (SELECT id FROM Person WHERE name = 'Jane')
The answer was already given by podiluska, just explaining how it works since it looks like you're new to MySql.
By giving an Alias to a table(like mother or father to the table person) you do something like a pseudo-table, that the MySql interprets as another table, so the join happens normally, just imagine there are 3 tables now. Person, Father and Mother, and they are all linked together by the join.