To improve its plugin - JMailAlerts - Kunena - Latest Forum Posts - I want to get all sub categories of the chosen top-category/top-categories. For this I need to alter the SQL query of this plugin.
I've tried to accive it with the following SQL query, but it doesn't only gives the the categories and its sub-categories of ALL Kunena categories, not just the two categories 31 and 36, and its sub-categories.
Code: Select all
SELECT *
FROM (
SELECT m.*, c.name AS catname, c.ordering AS catorder, c.parent_id AS catparent, t.message
FROM #__kunena_messages AS m
INNER JOIN #__kunena_messages_text AS t ON m.id = t.mesid
INNER JOIN #__kunena_categories AS c ON c.id = m.catid
WHERE (
m.catid=31 OR m.catid IN (
SELECT c2.id
FROM #__kunena_categories c1, #__kunena_categories c2
WHERE c1.parent_id=31 OR m.catid IN (
SELECT c2.id FROM #__kunena_categories c1, #__kunena_categories c2
WHERE c1.parent_id=31
)
)
)
OR (
m.catid=36 OR m.catid IN (
SELECT c2.id
FROM #__kunena_categories c1, #__kunena_categories c2
WHERE c1.parent_id=36 OR m.catid IN (
SELECT c2.id
FROM #__kunena_categories c1, #__kunena_categories c2
WHERE c1.parent_id=36
)
)
)
AND m.moved = 0 AND m.hold = 0 AND
FROM_UNIXTIME(m.time) > '2021-04-15074806'
ORDER BY m.time
DESC LIMIT 6
) AS x
ORDER BY x.catorder ASC, x.catparent ASC, x.catname ASC, x.thread ASC, x.time ASC
Code: Select all
SELECT * FROM (
SELECT m.*, c.name AS catname, c.ordering AS catorder, c.parent_id AS catparent, t.message
FROM #__kunena_messages AS m
INNER JOIN #__kunena_messages_text AS t ON m.id = t.mesid
INNER JOIN #__kunena_categories AS c ON c.id = m.catid
WHERE " . $catCondition . "
AND m.moved = 0 AND m.hold = 0 AND
FROM_UNIXTIME(m.time) > " . $emaildate . "
ORDER BY m.time DESC LIMIT " . $no_of_posts . ") AS x
ORDER BY x.catorder ASC, x.catparent ASC, x.catname ASC, x.thread ASC, x.time ASC
Code: Select all
// My own function
private function subcats($ids) {
$i = 0;
foreach($ids as $id) {
if ($i<1) {
$sqlcat = null;
}
else {
$sqlcat .= " OR ";
}
// $sqlcat .= 'm.catid = ' . $id; // Only gets the category chosen
// The following code shows all categories regardless where in the category three which is not wanted !!!
$sqlcat .= " (
m.catid=$id OR m.catid IN
( SELECT c2.id FROM #__kunena_categories c1, #__kunena_categories c2
WHERE c1.parent_id=$id OR m.catid IN
( SELECT c2.id FROM #__kunena_categories c1, #__kunena_categories c2
WHERE c1.parent_id=$id
)
)
)";
$i++;
}
return $sqlcat;
}
// Category filter
if ($catid)
{
$ids = explode(',', $catid);
$ids = ArrayHelper::toInteger($ids);
$catCondition = $this->subcats($ids); // My Function to show sub-categories
}
https://mariadb.com/kb/en/with/Below is an example of a Recursive CTE:
WITH RECURSIVE ancestors AS
( SELECT * FROM folks
WHERE name="Alex"
UNION
SELECT f.*
FROM folks AS f, ancestors AS a
WHERE f.id = a.father OR f.id = a.mother )
SELECT * FROM ancestors;
By including the following code:
Code: Select all
// My own function
private function subcats($ids) {
$i = 0;
foreach($ids as $id) {
if ($i<1) {
$sqlcat = null;
}
else {
$sqlcat .= " OR ";
}
// $sqlcat .= 'm.catid = ' . $id;
$sqlcat .= " (
m.catid=$id OR m.catid WITH RECURSIVE ancestors AS
( SELECT * FROM #__kunena_categories c
WHERE c.parent_id=$id
UNION
SELECT c.*
FROM #__kunena_categories AS c, ancestors AS a
WHERE c.id = a.parent_id=$id )
SELECT * FROM ancestors
)";
$i++;
}
return $sqlcat;
}
WITH RCTE AS
(
SELECT * , Id AS TopLevelParent
FROM dbo.Category c
UNION ALL
SELECT c.* , r.TopLevelParent
FROM dbo.Category c
INNER JOIN RCTE r ON c.ParentId = r.Id
)
SELECT
r.TopLevelParent AS ParentID
, r.Id AS ChildID
FROM RCTE r
ORDER BY ParentID;
https://stackoverflow.com/questions/455 ... categories
That I tried to incorporate in the same way in my code, but it throws an SQL-syntax error too.
Code: Select all
// My own function
private function subcats($ids) {
$i = 0;
foreach($ids as $id) {
if ($i<1) {
$sqlcat = null;
}
else {
$sqlcat .= " OR ";
}
// $sqlcat .= 'm.catid = ' . $id;
$sqlcat .= " (
m.catid=$id OR m.catid WITH RCTE AS
(
SELECT * , Id AS TopLevelParent
FROM dbo.#__kunena_categories c
UNION ALL
SELECT c.* , r.TopLevelParent
FROM dbo.#__kunena_categories c
INNER JOIN RCTE r ON c.ParentId = r.Id
)
SELECT
r.TopLevelParent AS ParentID
, r.Id AS ChildID
FROM RCTE r
ORDER BY ParentID
)";
$i++;
}
return $sqlcat;
}
Any suggestions?