Retrieving all 'Child' items using MySQL query - mysql

I am attempting to write a SQL query to generate a table containing all 'child' items for each 'parent' (in this case Element).
I have created a simplified instance of this problem below and setup a db-fiddle instance for sake of clarity.
Given the following dummy data:
-- -----------------------------------------------------
-- Table `Element`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Element` (
`idElement` INT NOT NULL AUTO_INCREMENT,
`Element_Name` VARCHAR(45) NULL,
PRIMARY KEY (`idElement`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Property`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Property`
(
`idProperty` INT NOT NULL AUTO_INCREMENT,
`Property_Text` VARCHAR(45) NULL,
`Property_Node_ID` INT NULL,
`Element_idElement` INT NOT NULL,
PRIMARY KEY (`idProperty`),
INDEX `fk_Property_Element1_idx` (`Element_idElement` ASC),
CONSTRAINT `fk_Property_Element1`
FOREIGN KEY (`Element_idElement`)
REFERENCES `Element` (`idElement`)
)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Property_2`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Property_2`
(
`idProperty_2` INT NOT NULL AUTO_INCREMENT,
`Property_2_Text` VARCHAR(45) NULL,
`Property_Node_ID` INT NULL,
`Element_idElement` INT NOT NULL,
PRIMARY KEY (`idProperty_2`),
INDEX `fk_Property_2_Element_idx` (`Element_idElement` ASC),
CONSTRAINT `fk_Property_2_Element`
FOREIGN KEY (`Element_idElement`)
REFERENCES `Element` (`idElement`)
)
ENGINE = InnoDB;
INSERT INTO `Element` (`idElement`, `Element_Name`)
VALUES (NULL, 'element_1');
INSERT INTO `Element` (`idElement`, `Element_Name`)
VALUES (NULL, 'element_2');
INSERT INTO `Property` (`idProperty`, `Property_Text`, `Property_Node_ID`, `Element_idElement`)
VALUES (NULL, 'property_a', NULL, '1');
INSERT INTO `Property` (`idProperty`, `Property_Text`, `Property_Node_ID`, `Element_idElement`)
VALUES (NULL, 'property_b', NULL, '1');
INSERT INTO `Property` (`idProperty`, `Property_Text`, `Property_Node_ID`, `Element_idElement`)
VALUES (NULL, 'property_c', NULL, '2');
INSERT INTO `Property_2` (`idProperty_2`, `Property_2_Text`, `Property_Node_ID`, `Element_idElement`)
VALUES (NULL, 'property_2_a', NULL, '1');
INSERT INTO `Property_2` (`idProperty_2`, `Property_2_Text`, `Property_Node_ID`, `Element_idElement`)
VALUES (NULL, 'property_2_b', NULL, '2');
INSERT INTO `Property_2` (`idProperty_2`, `Property_2_Text`, `Property_Node_ID`, `Element_idElement`)
VALUES (NULL, 'property_2_c', NULL, '2');
I would like to output the following where each unique combination of the element and its properties are displayed row-by-row.
They are ordered first by the element, then by the first property, and finally by the last property:
-------------------------------------
element | property | property_2
-------------------------------------
element_1 | property_a | property_2_a
element_1 | property_b | property_2_a
element_2 | property_c | property_2_b
element_2 | property_c | property_2_c
Please see the link to the db-fiddle:
https://www.db-fiddle.com/f/csqTVJFTtpodqPksQtyrbs/0. Any help would be greatly appreciated 😄

I don't really understand the problem - and the naming policy is confusing - but what part of it does the following fail to address?
SELECT e.Element_Name element
, p.Property_text property
, p2.Property_2_text property_2
FROM Element e
JOIN Property p
ON p.Element_idElement = e.idElement
JOIN Property_2 p2
ON p2.Element_idElement = e.idElement
ORDER
BY element
, property
, property_2;

Related

How to extract json data in mysql select?

I have two tables, and I want to use a value from primary table (here: person.ref) to extract some data from a json field in a secondary table (here: person_details):
create table person (
id int(8),
ref varchar(20),
primary key (id)
);
create table person_details (
id int(8),
details json,
primary key (id)
);
SELECT JSON_EXTRACT(details, CONCAT('$.', p.ref))
FROM person p
JOIN person_details d using (id);
The person_details data is like:
{
"ref1": {
...
}
}
But that does not matter, because the sql statement itself seems to be invalid:
Result:
#3143 - Invalid JSON path expression. The error is around character position 12.
Why?
Your code should work on MySQL >= 5.7. Check this dbfiddle:
https://dbfiddle.uk/esEJ9uHd
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ref` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `person_details` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`details` json,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `person` (`id`, `ref`) VALUES (1, 'ref1');
INSERT INTO `person` (`id`, `ref`) VALUES (2, 'ref1');
INSERT INTO `person_details` (`id`, `details`) VALUES (1, '{"ref1": {"name": "Barney"}}');
INSERT INTO `person_details` (`id`, `details`) VALUES (2, '{"ref1": {"name": "Willma"}}');
SELECT JSON_EXTRACT(details, CONCAT('$.', p.ref))
FROM person p
JOIN person_details d using (id);
While the answer above is correct, it did not solve my issue, but I had to add doublequotes around p.ref, so that the concatenation results in CONCAT($."p.ref"):
SELECT JSON_EXTRACT(details, CONCAT('$."', p.ref, '"'))
...

Can I run a SELECT query that depends on two rows from a table without using subqueries

Suppose the schemas are
users(id, name)
users_attributes(user_id, attribute_name, attribute_value)
Sample data:
--
-- Database: `sample_db`
--
CREATE DATABASE IF NOT EXISTS `sample_db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE `sample_db`;
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `users`
--
INSERT INTO `users` (`id`, `name`) VALUES
(1, 'Tim'),
(2, 'Joe'),
(3, 'Bob');
-- --------------------------------------------------------
--
-- Table structure for table `users_attributes`
--
CREATE TABLE `users_attributes` (
`user_id` int(11) NOT NULL,
`attribute_name` varchar(50) NOT NULL,
`attribute_value` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Dumping data for table `users_attributes`
--
INSERT INTO `users_attributes` (`user_id`, `attribute_name`, `attribute_value`) VALUES
(1, 'height', '10'),
(1, 'over_18', 'yes'),
(2, 'height', '5'),
(3, 'height', '7');
--
-- Indexes for dumped tables
--
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `users_attributes`
--
ALTER TABLE `users_attributes`
ADD UNIQUE KEY `user_id` (`user_id`,`attribute_name`,`attribute_value`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
COMMIT;
Right now I'm calling INNER JOIN on a specific attribute_name so my selection also returns that along with the user id and name. Now I want to exclude from whatever I selected, if they contain a certain other attribute. I know I can accomplish that by using a NOT IN (SELECT ...) conditional but can I do that without having to select again?
EDIT:
Attributes may or may not exist for all users. For example, I would like to fetch id, name, attribute_value where attribute_name = height but only if attribute_name over_18 does not exist or is 'no'

MySQL getting always error 1451 on update a single value in a table

I need a very little help.... I have two tables A and B where B contains a field that is in constraint key with the ID field of table A. Since I needed to update for a record of A the ID taken from another database, equal to the one I am working on, but with the ID in question "correct", so I did:
dropped the foreign key of table B on that field referenced to the ID of A
updated at all records on the old value of the field in B with the new value of reference ID where that field of B = to the old value
then I update the ID of table A with the new value and I get back error 1451 of foreign key on that field of B that I had already updated without problems even if I had dropped the foreign key in B already;
then I do SET FOREIGN_KEY_CHECKS = 0;
I try to update the ID of table A for that record with the new value but I always get error 1451 .....
since I dropped the foreign key and did the set as well, is there something else or command that I have to consider? thanks everyone in advance to all!
EDIT:
precisely I followed like this scenario:
CREATE TABLE sample_A (
ID bigint(20) UNSIGNED NOT NULL,
product varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE sample_B (
ID bigint(20) UNSIGNED NOT NULL,
ref_id_sample_A_id bigint(20) UNSIGNED NOT NULL,
document_name varchar(300) COLLATE utf8mb4_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE sample_A
ADD PRIMARY KEY ( ID )
ALTER TABLE sample_A
MODIFY ID bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=211388375;
COMMIT;
ALTER TABLE sample_B
ADD PRIMARY KEY ( ID );
ALTER TABLE sample_B
MODIFY ID bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=158;
ALTER TABLE sample_B
ADD CONSTRAINT fk_sample_A_sample_B_ref_id FOREIGN KEY ( ref_id_sample_A_id ) REFERENCES sample_A ( ID );
COMMIT;
INSERT INTO sample_A (ID, product) VALUES
(1, 'product 1'),
(211388370, 'product 2'),
(211388371, 'product 3'),
(211388372, 'product 4'),
(211388373, 'product 5');
INSERT INTO sample_B (ID, ref_id_sample_A_id, document_name) VALUES
(1, 211388372, 'document 1'),
(2, 211388371, 'document 2'),
(3, 1, 'document 3'),
(4, 211388373, 'document 4'),
(5, 1, 'document 5'),
(6, 211388370, 'document 6'),
(7, 211388371, 'document 7');
via phpMyAdmin , dropped foreign key fk_sample_A_sample_B_ref_id
UPDATE sample_B SET ref_id_sample_A_id = 211388369 WHERE ref_id_sample_A_id = 1; <---- OK
UPDATE sample_A SET ID = 211388369 WHERE ID = 1; <---- error 1451
SET FOREIGN_KEY_CHECKS = 0;
UPDATE sample_A SET ID = 211388369 WHERE ID = 1; <---- error 1451 again
next operation would be ALTER TABLE sample_B ADD CONSTRAINT fk_sample_A_sample_B_ref_id FOREIGN KEY ( ref_id_sample_A_id ) REFERENCES sample_A ( ID ); to restore foreign key
Nevermind... I solved... the problem was phpMyAdmin who had the option "check for foreigns enabled"... thanks anyway #Akina!

Duplicate entry '111-222' for key 'PRIMARY' when inserting a new value to MySQL database

I have a MySQL table running on AWS RDS with structure like the following:
CREATE TABLE `my_table` (
`col1` int(11) NOT NULL,
`col2` int(11) NOT NULL DEFAULT '0',
`f_name` varchar(45) DEFAULT NULL,
`l_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`col1`,`col2`),
KEY `idx_col1` (`col1`),
KEY `idx_col2` (`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The query
SELECT * FROM my_table WHERE col1=111 AND col2=222;
returns 0 row.
But when I run an insert query
INSERT INTO my_table
(col1, col2, f_name, l_name)
VALUES (111, 222, 'John', 'Doe')
I got an error saying
Duplicate entry '111-222' for key 'PRIMARY'.
Why does this happen? The table doesn't contain a row with col1=111 and col2=222.
There's already a row with values col1=111, col2=111, f_name='John', and l_name='Doe'. But I don't think this would cause a duplicate entry error.
=========================== EDIT ======================================
There's a trigger that generates the duplicate error. Here's the script to reproduce the error.
# Initialize the tables
CREATE TABLE `my_table` (
`col1` int(11) NOT NULL,
`col2` int(11) NOT NULL DEFAULT '0',
`f_name` varchar(45) DEFAULT NULL,
`l_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`col1`,`col2`),
KEY `idx_col1` (`col1`),
KEY `idx_col2` (`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `triggered_table` (
`col1` int(11) NOT NULL,
`col2` int(11) NOT NULL DEFAULT '0',
`update_date` bigint(20) DEFAULT NULL,
PRIMARY KEY (`col1`,`col2`),
KEY `idx_col1` (`col1`),
KEY `idx_col2` (`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# Insert the data that cause duplicate error
INSERT INTO triggered_table (col1, col2) VALUES (111, 222);
# Create the trigger
DELIMITER $$
CREATE TRIGGER weird_trigger AFTER INSERT
ON my_table
FOR EACH ROW
BEGIN
INSERT INTO triggered_table
(col1, col2)
VALUES (NEW.col1, NEW.col2);
END$$
DELIMITER ;
# Create the duplicate error
INSERT INTO my_table
(col1, col2, f_name, l_name)
VALUES (111, 222, 'John', 'Doe');
I really don't understand why the developers created the triggered_table table. Why didn't they put update_date column to my_table?
This is so weird.
All you have to do is:
Truncate your table then run (Assuming that you have only a test data but if not, you have to do some backup first)
INSERT INTO my_table
(col1, col2, f_name, l_name)
VALUES (111, 222, 'John', 'Doe')
Now if the error still exists, this is a pretty much problem.
Your error seems like you concatinated col1 and col2 as your primary key ('111-222')
You can try
select * from yourTable where FieldPrimary = '111-222' if it is already exists
The duplicate key error does not come from the my_table table but from the triggered_table table instead. When you add a row in triggered_table for the key (111, 222) and then add a new row in the my_table table (with the same key), your trigger will also try to add a new row with the key (111, 222) in your triggered_table. However there is already such a key in use and you will get the duplicate key error.
Depending on what you want to do with the my_table and triggered_table tables, you might want to change the trigger to use REPLACE INTO instead of INSERT INTO. Or you run a check with SELECT first to see if you need to add a new row or not. After that you can run an UPDATE query to change the value of update_date. But to answer your question, the duplicate key error comes from the duplicate key in the triggered_table table.

MYSQL - One Column Referenced to Multiple Table

Can a single column in a table can be referenced to multiple tables?
A very late answer, but for whoever is wondering & googeling.
YES this can be done, but it is NOT good practice and even though it is quite simple, it will probably blow up in your face if you're not very aware of what you are doing. Not recommended.
However, I can see uses. For instance, you have a large table of millions of records, and you want in exceptional cases link to unknown or multiple tables (in which case it better be many). With multiple tables, if you would make a foreign key for all of them, that would be a huge bloat in your database size. An unknown table would be possible for instance in a technical support system, where you want to link to record in a table where there might be a problem, and this could be (almost) all tables in the database, including future ones.
Of course you will need two fields to link with: a foreign key field and the name of the table it is linking to. Lets call them foreignId and linkedTable
linkedTable could be an enum or a string, preferrably enum (less space), but that's only possible if the different tables you want to link to, are fixed.
Let's give an extremely silly example. You have an enormous user table users of which some user can add exactly one personal set of data to their profile. This can be about a hobby, a pet, a sport they practice or their profession. Now this info is different in all four cases. (4 possible tables is in reality not enough to justify this structure)
Now let's say linkedTable is an enum with possible values pets, hobbies, sports and professions, which are the names of four differently structured tables. Let's say id is the pkey in all four of them.
You join for instance as follows:
SELECT * FROM users
LEFT JOIN pets ON linkedTable = 'pets' AND foreignId = pets.id
LEFT JOIN hobbies ON linkedTable = 'hobbies' AND foreignId = hobbies.id
LEFT JOIN sports ON linkedTable = 'sports' AND foreignId = sports.id
LEFT JOIN professions ON linkedTable = 'professions' AND foreignId = professions.id
This is just to give a basic jest. Since you probably only need the link in rare cases, you will more likely do the lookup in your programming language, like PHP, when you loop through the users (without join).
Want to try out? You can try it yourself with building this test database (make sure you use a test database):
CREATE TABLE IF NOT EXISTS `users` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(100) NOT NULL ,
`linkedTable` ENUM('pets','hobbies','sports','professions') NULL DEFAULT NULL ,
`foreignId` INT NULL DEFAULT NULL ,
PRIMARY KEY (`id`), INDEX (`linkedTable`)
) ;
CREATE TABLE IF NOT EXISTS `pets` (
`id` INT NOT NULL AUTO_INCREMENT ,
`animalTypeId` INT NOT NULL ,
`name` VARCHAR(100) NOT NULL ,
`colorId` INT NOT NULL ,
PRIMARY KEY (`id`), INDEX (`animalTypeId`), INDEX (`colorId`)
) ;
CREATE TABLE IF NOT EXISTS `hobbies` (
`id` INT NOT NULL AUTO_INCREMENT ,
`hobbyTypeId` INT NOT NULL ,
`hoursPerWeekSpend` INT NOT NULL ,
`websiteUrl` VARCHAR(300) NULL ,
PRIMARY KEY (`id`), INDEX (`hobbyTypeId`)
) ;
CREATE TABLE IF NOT EXISTS `sports` (
`id` INT NOT NULL AUTO_INCREMENT ,
`sportTypeId` INT NOT NULL ,
`hoursPerWeekSpend` INT NOT NULL ,
`nameClub` VARCHAR(100) NULL ,
`professional` TINYINT NOT NULL DEFAULT 0,
PRIMARY KEY (`id`), INDEX (`sportTypeId`)
) ;
CREATE TABLE IF NOT EXISTS `professions` (
`id` INT NOT NULL AUTO_INCREMENT ,
`professionId` INT NOT NULL ,
`hoursPerWeek` INT NOT NULL ,
`nameCompany` VARCHAR(100) NULL ,
`jobDescription` VARCHAR(400) NULL,
PRIMARY KEY (`id`), INDEX (`professionId`)
) ;
INSERT INTO `users` (`id`, `name`, `linkedTable`, `foreignId`)
VALUES
(NULL, 'Hank', 'pets', '1'),
(NULL, 'Peter', 'hobbies', '2'),
(NULL, 'Muhammed', 'professions', '1'),
(NULL, 'Clarice', NULL, NULL),
(NULL, 'Miryam', 'professions', '2'),
(NULL, 'Ming-Lee', 'hobbies', '1'),
(NULL, 'Drakan', NULL, NULL),
(NULL, 'Gertrude', 'sports', '2'),
(NULL, 'Mbase', NULL, NULL);
INSERT INTO `pets` (`id`, `animalTypeId`, `name`, `colorId`)
VALUES (NULL, '1', 'Mimi', '3'), (NULL, '2', 'Tiger', '8');
INSERT INTO `hobbies` (`id`, `hobbyTypeId`, `hoursPerWeekSpend`, `websiteUrl`)
VALUES (NULL, '123', '21', NULL), (NULL, '2', '1', 'http://www.freesoup.org');
INSERT INTO `sports` (`id`, `sportTypeId`, `hoursPerWeekSpend`, `nameClub`, `professional`)
VALUES (NULL, '2', '3', 'Racket to Racket', '0'), (NULL, '12', '34', NULL, '1');
INSERT INTO `professions` (`id`, `professionId`, `hoursPerWeek`, `nameCompany`, `jobDescription`)
VALUES (NULL, '275', '40', 'Ben & Jerry\'s', 'Ice cream designer'), (NULL, '21', '24', 'City of Dublin', 'Garbage collector');
Then run the first query.
Fun note for discussion: How would you index this?
If you mean "can a column in one table be used as a foreign key in multiple tables", then the answer is YES. This is the whole point of a relational database
Yes, you can do that so. here is a sample on how to do it:
Here is the table that has a column(CountryID) that will be referenced by multiple tables:
CREATE TABLE DLAccountingSystem.tblCountry
(
CountryID INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
CountryName VARCHAR(128) NOT NULL,
LastEditUser VARCHAR(128) NOT NULL,
LastEditDate DATETIME NOT NULL
) ENGINE=INNODB;
Here are the tables that is going to reference the column(CountryID):
CREATE TABLE DLAccountingSystem.tblCity
(
CityID INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
CountryID INT NOT NULL,
CityName VARCHAR(128) NOT NULL,
LastEditUser VARCHAR(128) NOT NULL,
LastEditDate DATETIME NOT NULL
) ENGINE=INNODB;
CREATE TABLE DLAccountingSystem.tblProvince
(
ProvinceID INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
CountryID INT NOT NULL,
ProvinceName VARCHAR(128) NOT NULL,
LastEditUser VARCHAR(128) NOT NULL,
LastEditDate DATETIME NOT NULL
) ENGINE=INNODB;
Here is how you create a reference to the column:
ALTER TABLE DLAccountingSystem.tblCity
ADD CONSTRAINT fk_tblcitycountryid FOREIGN KEY CountryID (CountryID)
REFERENCES DLAccountingSystem.tblCountry (CountryID)
ON DELETE NO ACTION
ON UPDATE NO ACTION
ALTER TABLE DLAccountingSystem.tblProvince
ADD CONSTRAINT fk_tblprovincecountryid FOREIGN KEY CountryID (CountryID)
REFERENCES DLAccountingSystem.tblCountry (CountryID)
ON DELETE NO ACTION
ON UPDATE NO ACTION
here is a table that has column that references different columns from (CountryID, ProvinceID, CityID) multiple tables(I Don't personally advice this way of table structuring. Just my opinion no offense ;) )
CREATE TABLE DLAccountingSystem.tblPersons
(
PersonID INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
PlaceID INT NOT NULL,
PlaceTypeID INT NOT NULL, -- this property refers to what table are you referencing.
//Other properties here.....
) ENGINE=INNODB;
you should also have a lookup table that would contain the PlaceType:
CREATE TABLE DLAccountingSystem.tblPlaceType
(
PlaceTypeID INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
PlaceTypeName INT NOT NULL
//Other properties here.....
) ENGINE=INNODB;
here is how you fetch it:
SELECT p1.PersonID,
tcity.CityName,
tprov.ProvinceName,
tcoun.CountryName
FROM DLAccountingSystem.tblPersons p1
LEFT JOIN (SELECT p2.PersonID, p2.PlaceTypeID, c.CityName FROM DLAccountingSystem.tblPersons p2 INNER JOIN DLAccountingSystem.tblCity c ON p2.ObjectID = c.CityID WHERE PlaceTypeID = #CityTypeID) tcity ON p1.PersonID = tcity.PersonID
LEFT JOIN (SELECT p2.PersonID, p2.PlaceTypeID, c.ProvinceName FROM DLAccountingSystem.tblPersons p2 INNER JOIN DLAccountingSystem.tblProvince c ON p2.ObjectID = c.ProvinceID WHERE PlaceTypeID = #ProvinceTypeID) tprov ON p1.PersonID = tprov.PersonID
LEFT JOIN (SELECT p2.PersonID, p2.PlaceTypeID, c.CountryName FROM DLAccountingSystem.tblPersons p2 INNER JOIN DLAccountingSystem.tblCountry c ON p2.ObjectID = c.CountryID WHERE PlaceTypeID = #CountryTypeID) tcoun ON p1.PersonID = tcoun.PersonID
you can select from other tables like
A same column or set of columns can act as a parent and/or as a child endpoint of a foreign key or foreign keys.