Assuming the following tables:
area
-id
-title
properties
-id
-title
-area_id
categories
-id
-title
properties_categories
-property_id
-category_id
The following query is very close to the correct answer but is not correct. Could you advise what the correct query is?
select a.id, a.title, count(p.id)
FROM area AS a,properties AS p, properties_categories AS pc
WHERE a.id = p.area_id
AND pc.category_id IN (1,2,3)
AND pc.property_id = p.id
GROUP BY a.id;
OR
SELECT A.id, A.title, COUNT(B.id)
FROM area A LEFT JOIN properties B
ON A.id=B.area_id
JOIN properties_categories C
ON C.property_id=B.id
WHERE C.category_id IN (1,2,3)
GROUP BY A.id, A.title;
If I write a query where the following only draws from the area and properties table you have the correct results.
SELECT A.id, A.title, COUNT(B.id) FROM area A LEFT JOIN properties B ON A.id=B.area_id GROUP BY A.id, A.title
Here is the data dump to experiment with:
CREATE TABLE `area` (
`id` int(10) UNSIGNED NOT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `area` (`id`, `title`) VALUES
(2, 'Test1'),
(3, 'Test2'),
(4, 'Test3'),
(5, 'Test4'),
(6, 'Test5');
CREATE TABLE `categories` (
`id` int(10) UNSIGNED NOT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `categories` (`id`, `title`) VALUES
(1, 'Category A'),
(2, 'Category B'),
(3, 'Category C'),
(4, 'Category D'),
(5, 'Category E'),
(6, 'Category F');
CREATE TABLE `properties` (
`id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`area_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `properties` (`id`, `name`, `area_id`) VALUES
(2, 'Property A', 2),
(3, 'Property B', 2),
(4, 'Property C', 2),
(5, 'Property D', 2),
(7, 'Property E', 2),
(8, 'Property F', 2),
(10, 'Property G', 2),
(11, 'Property H', 2),
(12, 'Property I', 2),
(13, 'Property J', 2),
(14, 'Property K', 2),
(19, 'Property L', 2),
(20, 'Property M', 4),
(21, 'Property O', 2),
(22, 'Property P', 2),
(23, 'Property Q', 2),
(24, 'Property R', 2),
(27, 'Property S', NULL),
(29, 'Property T', 2),
(30, 'Property U', 2),
(32, 'Property V', 2),
(33, 'Property W', 2),
(34, 'Property X', 5),
(35, 'Property Y', 5),
(36, 'Property Z', 5),
(37, 'Property A1', 5),
(38, 'Property A2', 3),
(39, 'Property A3', 6);
CREATE TABLE `properties_categories` (
`category_id` int(11) NOT NULL,
`property_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `properties_categories` (`category_id`, `property_id`) VALUES
(2, 2),
(6, 2),
(2, 3),
(6, 3),
(2, 4),
(6, 4),
(2, 5),
(6, 5),
(2, 7),
(6, 7),
(2, 8),
(6, 8),
(2, 10),
(6, 10),
(2, 11),
(6, 11),
(2, 12),
(6, 12),
(2, 13),
(6, 13),
(2, 14),
(6, 14),
(5, 7),
(5, 3),
(5, 14),
(5, 4),
(5, 12),
(5, 11),
(5, 13),
(5, 5),
(5, 10),
(5, 8),
(2, 20),
(3, 20),
(2, 19),
(6, 19),
(2, 21),
(2, 22),
(2, 23),
(5, 23),
(6, 23),
(1, 22),
(2, 24),
(6, 24),
(2, 29),
(2, 30),
(5, 30),
(2, 33),
(5, 33),
(6, 33),
(2, 32),
(5, 32),
(6, 32),
(1, 34),
(2, 34),
(3, 34),
(4, 34),
(2, 35),
(5, 35),
(2, 36),
(4, 36),
(5, 36),
(2, 37),
(4, 37),
(5, 37),
(2, 38),
(2, 39),
(4, 39),
(5, 39),
(1, 39),
(5, 24),
(4, 38);
Try this:
SELECT A.id, A.title, COUNT(B.id)
FROM area A LEFT JOIN properties B
ON A.id=B.area_id
JOIN properties_categories C
ON C.property_id=B.id
WHERE C.category_id IN (1,2,3)
GROUP BY A.id, A.title;
See MySQL Join Made Easy for insights on using joins in mysql.
Related
How do I get from a table all nodes that have no parent nodes?
I am using a (Closure Table) template.
I need to get all nodes that have no parent nodes.
Consider the fact that each node refers to itself. That is, each node itself is a parent and child node in relation to itself.
It looks something like this.
Below I am showing a test database.
-- phpMyAdmin SQL Dump
-- version 5.1.0
-- https://www.phpmyadmin.net/
--
-- Host: localhost
-- Generation Time: Oct 15, 2021 at 06:30 PM
-- Server version: 8.0.25
-- PHP Version: 8.0.3
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `closure`
--
-- --------------------------------------------------------
--
-- Table structure for table `category_name`
--
CREATE TABLE `category_name` (
`id` bigint NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_ru_0900_ai_ci DEFAULT NULL,
`level` int DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_ru_0900_ai_ci;
--
-- Dumping data for table `category_name`
--
INSERT INTO `category_name` (`id`, `name`, `level`) VALUES
(1, 'Electronics', 0),
(2, 'TV sets', 0),
(3, 'Sensory', 0),
(4, 'Backlit', 0),
(5, 'On wheels', 0),
(6, 'Anti-glare', 0),
(7, 'Super thin', 0),
(8, 'Wall', 0),
(9, 'Telephone', 0),
(10, 'Shell', 0),
(11, 'Button', 0),
(12, 'Sensory', 0),
(13, 'Retractable', 0),
(14, 'Auto', 0),
(15, 'Manual', 0),
(16, 'For home', 0),
(17, 'For bathroom', 0),
(18, 'Rug', 0),
(19, 'With animals', 0),
(20, 'Obstruction', 0),
(21, 'Soap dish ', 0),
(22, 'With holes', 0),
(23, 'Transparent', 0),
(24, 'For kitchen', 0),
(25, 'Pans', 0),
(26, 'With handles', 0),
(27, 'Non-stick', 0),
(28, 'pans', 0),
(29, 'Steam', 0),
(30, 'With lids', 0),
(31, 'Test', 0);
-- --------------------------------------------------------
--
-- Table structure for table `tree_path`
--
CREATE TABLE `tree_path` (
`children` bigint NOT NULL,
`parent` bigint NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_ru_0900_ai_ci;
--
-- Dumping data for table `tree_path`
--
INSERT INTO `tree_path` (`children`, `parent`) VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 1),
(6, 1),
(7, 1),
(8, 1),
(9, 1),
(10, 1),
(11, 1),
(12, 1),
(13, 1),
(14, 1),
(15, 1),
(2, 2),
(3, 2),
(4, 2),
(5, 2),
(6, 2),
(7, 2),
(8, 2),
(3, 3),
(4, 3),
(5, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 6),
(8, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 9),
(11, 9),
(12, 9),
(13, 9),
(14, 9),
(15, 9),
(10, 10),
(11, 10),
(12, 10),
(11, 11),
(12, 12),
(13, 13),
(14, 13),
(15, 13),
(14, 14),
(15, 15),
(16, 16),
(17, 16),
(18, 16),
(19, 16),
(20, 16),
(21, 16),
(22, 16),
(23, 16),
(24, 16),
(25, 16),
(26, 16),
(27, 16),
(28, 16),
(29, 16),
(30, 16),
(17, 17),
(18, 17),
(19, 17),
(20, 17),
(21, 17),
(22, 17),
(23, 17),
(18, 18),
(19, 18),
(20, 18),
(19, 19),
(20, 20),
(21, 21),
(22, 21),
(23, 21),
(22, 22),
(23, 23),
(24, 24),
(25, 24),
(26, 24),
(27, 24),
(28, 24),
(29, 24),
(30, 24),
(25, 25),
(26, 25),
(27, 25),
(26, 26),
(27, 27),
(28, 28),
(29, 28),
(30, 28),
(29, 29),
(30, 30);
--
-- Indexes for dumped tables
--
--
-- Indexes for table `category_name`
--
ALTER TABLE `category_name`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `tree_path`
--
ALTER TABLE `tree_path`
ADD PRIMARY KEY (`children`,`parent`),
ADD KEY `FK_PARENT` (`parent`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `category_name`
--
ALTER TABLE `category_name`
MODIFY `id` bigint NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=33;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `tree_path`
--
ALTER TABLE `tree_path`
ADD CONSTRAINT `FK_CHILDREN` FOREIGN KEY (`children`) REFERENCES `category_name` (`id`) ON DELETE CASCADE,
ADD CONSTRAINT `FK_PARENT` FOREIGN KEY (`parent`) REFERENCES `category_name` (`id`) ON DELETE CASCADE;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION */;
Perhaps the answer will be like this.
+----+--------------+-------+----------+--------+
| id | name | level | children | parent |
+----+--------------+-------+----------+--------+
| 1 | Electronics | 0 | 1 | 1 |
| 16| For home | 0 | 16 | 16 |
+----+--------------+-------+----------+--------+
I'd use NOT EXISTS () to check that there are no parent rows in the tree_path table (other than itself).
SELECT
*
FROM
category_name c
WHERE
NOT EXISTS (
SELECT *
FROM tree_path t
WHERE t.parent != c.id
AND t.children = c.id
)
AND EXISTS (
SELECT *
FROM tree_path t
WHERE t.parent = c.id
AND t.children = c.id
)
Demo : https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=55698aa8b51f99d42db63feda15148a7
(Edited to exclude categories that are not in tree_path)
This question already has an answer here:
How to get only the first level of depth child nodes?
(1 answer)
Closed 1 year ago.
I am using tree storage. Closure Table pattern.
https://towardsdatascience.com/closure-table-pattern-to-model-hierarchies-in-nosql-c1be6a87e05b
How to get child nodes without grandchildren and great-grandchildren?
I have a sql query:
SELECT p.id, p.name, count(*) - l.level AS level
FROM tree_Path t,
( SELECT count(*) -1 AS level
FROM tree_path
WHERE children = 3
) l,
( SELECT *
FROM category_name f
INNER JOIN tree_Path t
ON f.id = t.children
WHERE t.parent = 3
AND t.children!=t.parent
) p
WHERE p.children = t.children
GROUP BY p.id, p.name, l.level;
It returns a complete tree of descendants, including grandchildren and great-grandchildren.
+----+----------------------------+-------+
| id | name | level |
+----+----------------------------+-------+
| 7 | Audio & Video Accessories | 2 |
| 8 | Camera & Photo Accessories | 2 |
| 15 | 3D Glasses | 3 |
| 16 | Antennas | 3 |
| 17 | Accessory Bundles | 3 |
| 18 | Bags & Cases | 3 |
+----+----------------------------+-------+
I need to return my children without grandchildren and great-grandchildren.
+----+----------------------------+-------+
| id | name | level |
+----+----------------------------+-------+
| 7 | Audio & Video Accessories | 2 |
| 8 | Camera & Photo Accessories | 2 |
+----+----------------------------+-------+
How to do it?
DB TEST
-- phpMyAdmin SQL Dump
-- version 5.1.0
-- https://www.phpmyadmin.net/
--
-- Host: localhost
-- Generation Time: Aug 02, 2021 at 01:15 PM
-- Server version: 8.0.25
-- PHP Version: 8.0.3
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `closure_table`
--
-- --------------------------------------------------------
--
-- Table structure for table `category_name`
--
CREATE TABLE `category_name` (
`id` bigint NOT NULL,
`name` varchar(255) COLLATE utf8mb4_ru_0900_ai_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_ru_0900_ai_ci;
--
-- Dumping data for table `category_name`
--
INSERT INTO `category_name` (`id`, `name`) VALUES
(1, 'Electronics'),
(2, 'Computers'),
(3, 'Accessories & Supplies'),
(4, 'Camera & Photo'),
(5, 'Computer accessories and peripherals'),
(6, 'Computer components'),
(7, 'Audio & Video Accessories'),
(8, 'Camera & Photo Accessories'),
(9, 'Accessories'),
(10, 'Bags & Cases'),
(11, 'Audio & Video Accessories'),
(12, 'Blank Media'),
(13, 'Computer screws'),
(14, 'Table Barebones'),
(15, '3D Glasses'),
(16, 'Antennas'),
(17, 'Accessory Bundles'),
(18, 'Bags & Cases'),
(19, 'Accessory Kits'),
(20, 'Bags & Cases'),
(21, 'Bag & Case Accessories'),
(22, 'Binocular Cases'),
(23, 'Computer headsets'),
(24, 'Computer microphones'),
(25, 'Discs BD-R'),
(26, 'Discs BD-RE'),
(27, 'bolts'),
(28, 'frame'),
(29, 'lamps'),
(30, 'coasters');
-- --------------------------------------------------------
--
-- Table structure for table `tree_path`
--
CREATE TABLE `tree_path` (
`children` bigint NOT NULL,
`parent` bigint NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_ru_0900_ai_ci;
--
-- Dumping data for table `tree_path`
--
INSERT INTO `tree_path` (`children`, `parent`) VALUES
(1, 1),
(3, 1),
(4, 1),
(7, 1),
(8, 1),
(9, 1),
(10, 1),
(15, 1),
(16, 1),
(17, 1),
(18, 1),
(19, 1),
(20, 1),
(21, 1),
(22, 1),
(2, 2),
(5, 2),
(6, 2),
(11, 2),
(12, 2),
(13, 2),
(14, 2),
(23, 2),
(24, 2),
(25, 2),
(26, 2),
(27, 2),
(28, 2),
(29, 2),
(30, 2),
(3, 3),
(7, 3),
(8, 3),
(15, 3),
(16, 3),
(17, 3),
(18, 3),
(4, 4),
(9, 4),
(10, 4),
(19, 4),
(20, 4),
(21, 4),
(22, 4),
(5, 5),
(11, 5),
(12, 5),
(23, 5),
(24, 5),
(25, 5),
(26, 5),
(6, 6),
(13, 6),
(14, 6),
(27, 6),
(28, 6),
(29, 6),
(30, 6),
(7, 7),
(15, 7),
(16, 7),
(8, 8),
(17, 8),
(18, 8),
(9, 9),
(19, 9),
(20, 9),
(10, 10),
(21, 10),
(22, 10),
(11, 11),
(23, 11),
(24, 11),
(12, 12),
(25, 12),
(26, 12),
(13, 13),
(27, 13),
(28, 13),
(14, 14),
(29, 14),
(30, 14),
(15, 15),
(16, 16),
(17, 17),
(18, 18),
(19, 19),
(20, 20),
(21, 21),
(22, 22),
(23, 23),
(24, 24),
(25, 25),
(26, 26),
(27, 27),
(28, 28),
(29, 29),
(30, 30);
--
-- Indexes for dumped tables
--
--
-- Indexes for table `category_name`
--
ALTER TABLE `category_name`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `tree_path`
--
ALTER TABLE `tree_path`
ADD PRIMARY KEY (`children`,`parent`),
ADD KEY `FK_PARENT` (`parent`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `category_name`
--
ALTER TABLE `category_name`
MODIFY `id` bigint NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=31;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `tree_path`
--
ALTER TABLE `tree_path`
ADD CONSTRAINT `FK_CHILDREN` FOREIGN KEY (`children`) REFERENCES `category_name` (`id`) ON DELETE CASCADE,
ADD CONSTRAINT `FK_PARENT` FOREIGN KEY (`parent`) REFERENCES `category_name` (`id`) ON DELETE CASCADE;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION */;
Assuming you want level = 2 results and no greater descendants, use a HAVING clause:
SELECT p.id, p.name, count(*) - l.level AS levelx
FROM tree_path t,
( SELECT count(*) -1 AS level
FROM tree_path
WHERE children = 3
) l,
( SELECT *
FROM category_name f
INNER JOIN tree_path t
ON f.id = t.children
WHERE t.parent = 3
AND t.children!=t.parent
) p
WHERE p.children = t.children
GROUP BY p.id, p.name, l.level
HAVING levelx = 2
;
See your SQL in a fiddle:
Working test case with adjusted SQL with HAVING clause
I am using tree storage. Closure Table pattern.
https://towardsdatascience.com/closure-table-pattern-to-model-hierarchies-in-nosql-c1be6a87e05b
How to get child nodes without grandchildren and great-grandchildren? For example, from ancestor C, get descendants G, H and F.
Below I show the Closure Table database as an example.
DB Closure Table
-- phpMyAdmin SQL Dump
-- version 5.1.0
-- https://www.phpmyadmin.net/
--
-- Host: localhost
-- Generation Time: Aug 02, 2021 at 01:15 PM
-- Server version: 8.0.25
-- PHP Version: 8.0.3
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET #OLD_CHARACTER_SET_CLIENT=##CHARACTER_SET_CLIENT */;
/*!40101 SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS */;
/*!40101 SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `closure_table`
--
-- --------------------------------------------------------
--
-- Table structure for table `category_name`
--
CREATE TABLE `category_name` (
`id` bigint NOT NULL,
`name` varchar(255) COLLATE utf8mb4_ru_0900_ai_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_ru_0900_ai_ci;
--
-- Dumping data for table `category_name`
--
INSERT INTO `category_name` (`id`, `name`) VALUES
(1, 'Electronics'),
(2, 'Computers'),
(3, 'Accessories & Supplies'),
(4, 'Camera & Photo'),
(5, 'Computer accessories and peripherals'),
(6, 'Computer components'),
(7, 'Audio & Video Accessories'),
(8, 'Camera & Photo Accessories'),
(9, 'Accessories'),
(10, 'Bags & Cases'),
(11, 'Audio & Video Accessories'),
(12, 'Blank Media'),
(13, 'Computer screws'),
(14, 'Table Barebones'),
(15, '3D Glasses'),
(16, 'Antennas'),
(17, 'Accessory Bundles'),
(18, 'Bags & Cases'),
(19, 'Accessory Kits'),
(20, 'Bags & Cases'),
(21, 'Bag & Case Accessories'),
(22, 'Binocular Cases'),
(23, 'Computer headsets'),
(24, 'Computer microphones'),
(25, 'Discs BD-R'),
(26, 'Discs BD-RE'),
(27, 'bolts'),
(28, 'frame'),
(29, 'lamps'),
(30, 'coasters');
-- --------------------------------------------------------
--
-- Table structure for table `tree_path`
--
CREATE TABLE `tree_path` (
`children` bigint NOT NULL,
`parent` bigint NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_ru_0900_ai_ci;
--
-- Dumping data for table `tree_path`
--
INSERT INTO `tree_path` (`children`, `parent`) VALUES
(1, 1),
(3, 1),
(4, 1),
(7, 1),
(8, 1),
(9, 1),
(10, 1),
(15, 1),
(16, 1),
(17, 1),
(18, 1),
(19, 1),
(20, 1),
(21, 1),
(22, 1),
(2, 2),
(5, 2),
(6, 2),
(11, 2),
(12, 2),
(13, 2),
(14, 2),
(23, 2),
(24, 2),
(25, 2),
(26, 2),
(27, 2),
(28, 2),
(29, 2),
(30, 2),
(3, 3),
(7, 3),
(8, 3),
(15, 3),
(16, 3),
(17, 3),
(18, 3),
(4, 4),
(9, 4),
(10, 4),
(19, 4),
(20, 4),
(21, 4),
(22, 4),
(5, 5),
(11, 5),
(12, 5),
(23, 5),
(24, 5),
(25, 5),
(26, 5),
(6, 6),
(13, 6),
(14, 6),
(27, 6),
(28, 6),
(29, 6),
(30, 6),
(7, 7),
(15, 7),
(16, 7),
(8, 8),
(17, 8),
(18, 8),
(9, 9),
(19, 9),
(20, 9),
(10, 10),
(21, 10),
(22, 10),
(11, 11),
(23, 11),
(24, 11),
(12, 12),
(25, 12),
(26, 12),
(13, 13),
(27, 13),
(28, 13),
(14, 14),
(29, 14),
(30, 14),
(15, 15),
(16, 16),
(17, 17),
(18, 18),
(19, 19),
(20, 20),
(21, 21),
(22, 22),
(23, 23),
(24, 24),
(25, 25),
(26, 26),
(27, 27),
(28, 28),
(29, 29),
(30, 30);
--
-- Indexes for dumped tables
--
--
-- Indexes for table `category_name`
--
ALTER TABLE `category_name`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `tree_path`
--
ALTER TABLE `tree_path`
ADD PRIMARY KEY (`children`,`parent`),
ADD KEY `FK_PARENT` (`parent`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `category_name`
--
ALTER TABLE `category_name`
MODIFY `id` bigint NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=31;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `tree_path`
--
ALTER TABLE `tree_path`
ADD CONSTRAINT `FK_CHILDREN` FOREIGN KEY (`children`) REFERENCES `category_name` (`id`) ON DELETE CASCADE,
ADD CONSTRAINT `FK_PARENT` FOREIGN KEY (`parent`) REFERENCES `category_name` (`id`) ON DELETE CASCADE;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION */;
Here's a solution:
select p1.* from tree_path as p1
left outer join (tree_path as p2 join tree_path as p3 on p2.children = p3.parent)
on p2.parent = p1.parent
and p3.children = p1.children
and p2.parent <> p2.children
and p3.parent <> p3.children
where p1.parent = 3 and p2.parent is NULL;
+----------+--------+
| children | parent |
+----------+--------+
| 3 | 3 |
| 7 | 3 |
| 8 | 3 |
+----------+--------+
Change the p1.parent=7 and you get this output:
+----------+--------+
| children | parent |
+----------+--------+
| 7 | 7 |
| 15 | 7 |
| 16 | 7 |
+----------+--------+
Here's the way it works: immediate children are descendants where there is a path from parent to child, but there is no path from parent through a third node to the child. So we try to join to such a path (p2->p3) and if none is found, then all columns of p2 and p3 will be NULL.
I have this data and table structure,I am creating MySQL stored procedure to sum all the amount in the leftchild of the parentid, I don't have enough knowledge in stored procedure.and I need some help please because I'm lost.
CREATE TABLE IF NOT EXISTS `mytree` (
`parentid` int(11) NOT NULL,
`memberid` int(11) NOT NULL,
`position` char(1) NOT NULL,
`amount` decimal(10,2) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `mytree` (`parentid`, `memberid`, `position`, `amount`) VALUES
(8, 27, 'R', 0.00),
(8, 28, 'L', 0.00),
(24, 26, 'R', 0.00),
(0, 1, '', 5500.00),
(24, 25, 'L', 0.00),
(21, 24, 'L', 500.00),
(21, 23, 'R', 0.00),
(18, 20, 'R', 1500.00),
(18, 19, 'L', 0.00),
(15, 18, 'R', 2000.00),
(15, 17, 'L', 0.00),
(13, 16, 'L', 0.00),
(13, 15, 'R', 2500.00),
(12, 14, 'R', 0.00),
(12, 13, 'L', 3000.00),
(10, 12, 'R', 3500.00),
(10, 11, 'L', 0.00),
(7, 10, 'R', 4000.00),
(7, 9, 'L', 0.00),
(5, 8, 'R', 500.00),
(5, 7, 'L', 4500.00),
(1, 6, 'R', 0.00),
(1, 5, 'L', 5500.00),
(20, 22, 'R', 0.00),
(20, 21, 'L', 1000.00);
here is my stored proc
CREATE DEFINER=`root`#`localhost` PROCEDURE `count_left_right_amount`(IN `p_memid` INT, OUT `tot_left_amount` DECIMAL(10,2))
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE row_total decimal(10,2);
DECLARE total decimal(10,2);
DECLARE m_left int;
DECLARE run_left int;
DECLARE p_id int;
set total = 0;
select memberid into p_id from mytree where position = 'L' AND parentid = p_memid;
WHILE p_id != 0 DO
select amount into row_total from mytree where parentid = p_id
GROUP BY parentid;
select memberid into m_left from mytree where parentid = p_id;
set total = total + row_total;
set p_id = m_left;
END WHILE;
END
Example if the parentid is 5 ,so the leftchild is 7 then go down to his subtree sum it all,so the total amount in the left child is '22500'? please correct me if I'm wrong.
please help me.
Thank you in advance.
I need some help please,I'm having problem with the SP,how can I prevent this not to get recursive limit SQL ERROR(1456).Is there a way to change this SP not to use recursive...what I'm trying to achieve is to sum to all the amount in my left subtree on a given parentid...for example I have parentid 5,so my left is 7 so I want to sum all his amount on his subtree it's(22,500)if I'm not wrong.
Thank you in advance.
I have this table structure
CREATE TABLE `mytree` (
`parentid` INT(11) NOT NULL,
`memberid` INT(11) NOT NULL,
`position` CHAR(1) NOT NULL,
`amount` DECIMAL(10,2) NOT NULL,
UNIQUE INDEX `ck1tree` (`memberid`),
UNIQUE INDEX `ck2tree` (`parentid`, `position`)
)
COLLATE='latin1_swedish_ci'
ENGINE=MyISAM
;
and here is my data in the table mytree
INSERT INTO `mytree` (`parentid`, `memberid`, `position`, `amount`) VALUES
(8, 27, 'R', 0.00),
(8, 28, 'L', 0.00),
(24, 26, 'R', 0.00),
(0, 1, '', 5500.00),
(24, 25, 'L', 0.00),
(21, 24, 'L', 500.00),
(21, 23, 'R', 0.00),
(18, 20, 'R', 1500.00),
(18, 19, 'L', 0.00),
(15, 18, 'R', 2000.00),
(15, 17, 'L', 0.00),
(13, 16, 'L', 0.00),
(13, 15, 'R', 2500.00),
(12, 14, 'R', 0.00),
(12, 13, 'L', 3000.00),
(10, 12, 'R', 3500.00),
(10, 11, 'L', 0.00),
(7, 10, 'R', 4000.00),
(7, 9, 'L', 0.00),
(5, 8, 'R', 500.00),
(5, 7, 'L', 4500.00),
(1, 6, 'R', 0.00),
(1, 5, 'L', 5500.00),
(20, 22, 'R', 0.00),
(20, 21, 'L', 1000.00);
CREATE DEFINER=`root`#`localhost` PROCEDURE `sum_left_amount`(IN `p_memid` INT, OUT `tot_left_amount` DECIMAL(10,2))
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE a decimal(10,2);
DECLARE m int;
DECLARE s decimal(10,2);
select memberid, amount into m, a from mytree
where parentid = p_memid and position = 'L';
call sum_left_amount(m,s);
set tot_left_amount = a + s;
END