【问题标题】:correlated subquery within CTE is not synchronisedCTE 中的相关子查询不同步
【发布时间】:2021-04-10 02:29:30
【问题描述】:

鉴于下面的查询,

我面临的问题如下

 WHERE
      initial_categories.id = categories.id 

在上述条件下,categories.id 应与外部 categories.id 同步。

这在我使用 sqlite 时有效(categories.id 与外部值同步)

但是,当我出于某种原因在条件中使用mysql 时,categories.id 仅从外部categories.id 中获取第一个值,之后它不会改变(换句话说,它不同步),更具体地说,categories.id 在 CTE 中始终具有值 1

我不知道是什么问题。有什么想法吗?

SELECT
   *,
   (
      SELECT
         id 
      FROM
         threads 
      WHERE
         threads.category_id IN 
         (
            WITH recursive recursive_categories AS 
            (
               SELECT
                  initial_categories.id 
               FROM
                  categories AS initial_categories 
               WHERE
                  initial_categories.id = categories.id 
               UNION ALL
               SELECT
                  remaining_categories.id 
               FROM
                  recursive_categories 
                  JOIN
                     categories AS remaining_categories 
                     ON recursive_categories.id = remaining_categories.parent_id 
            )
            SELECT
               id 
            FROM
               recursive_categories 
         )
      ORDER BY
         updated_at DESC limit 1
   )
   AS recently_active_thread_id 
FROM
   "categories" 
WHERE
   "parent_id" IS NULL 
   AND "categories"."group_category_id" IN 
   (
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8
   )

-----查询的目的------

我有桌子

categories

- id
- parent_id
- title

threads

- id
- category_id
- title

现在category 可以拥有sub-categories,它们是使用categories 表中的parent_id 找到的。

具有sub-categoriescategory 不直接与thread 关联

只有没有sub-categoriescategorythreads 相关联

举个例子

Computer -> MAC -> MacBook 
Computer -> WINDOWS -> HP

在上面的示例中,只有 categories MacBookHPthreads 关联

我想通过下面的查询来实现的是在给定父类别

的所有sub-categories 中找到最新线程

继续上述示例,我想找到与Computer 类别间接关联的最新线程

【问题讨论】:

  • 您能解释一下您要做什么,以及示例数据和期望的结果吗?
  • 我刚刚添加了另一个部分来解释查询的目的。请看一下

标签: mysql sql sqlite correlated-subquery


【解决方案1】:

如果您想确保categories.id 将是外部 类别ID,您可以为外部categories 起别名,例如:

FROM categories AS outer_categories

WHERE 子句是:

WHERE initial_categories.id = outer_categories.id 

所以改成:

SELECT outer_categories.*,
   (
      SELECT id 
      FROM threads 
      WHERE category_id IN (
            WITH recursive recursive_categories AS (
               SELECT initial_categories.id 
               FROM categories AS initial_categories 
               WHERE initial_categories.id = outer_categories.id 
               UNION ALL
               SELECT remaining_categories.id 
               FROM recursive_categories JOIN categories AS remaining_categories 
               ON recursive_categories.id = remaining_categories.parent_id 
            )
            SELECT id FROM recursive_categories 
         )
      ORDER BY updated_at DESC limit 1
   ) AS recently_active_thread_id 
FROM categories AS outer_categories
WHERE outer_categories.parent_id IS NULL 
  AND outer_categories.group_category_id IN (1, 2, 3, 4, 5, 6, 7, 8)

【讨论】:

  • 感谢您的回复。不幸的是,这不起作用,这是有道理的,因为如果 categories.id 完全未知,我认为它会出错。但就我而言,它只是不会改变价值
  • 而且很奇怪sqlite没有发生这种情况
  • @OrestisuRic 在 WHERE 子句中 outer_categories.id 肯定指的是外部类别表,这就是您想要的。也不要依赖 SQLite 代码,因为它有自己的特殊功能。所以 SQLite 中的工作代码并不总是在其他数据库中工作。
  • 我使用sqlite 仅用于测试目的,在这种特殊情况下,它似乎正在处理sqlite 而不是mysql。甚至在使用别名outer_catefories 之前,我认为它仍然指的是outer_categories,因为我每次在子查询中使用categories 时都使用了别名。
  • 但是问题依然存在
【解决方案2】:

我创建了一个返回最新线程ID的函数。

基本上,我将查询和子查询移到了一个函数中,它可以工作

CREATE FUNCTION `recently_active_thread`(category_id INT) RETURNS int
BEGIN 
  DECLARE recentThreadId INT;
  SELECT id 
  INTO recentThreadId
  FROM   threads 
  WHERE  threads.category_id IN ( WITH recursive recursive_categories AS 
                                 ( 
                                        SELECT initial_categories.id 
                                        FROM   categories AS initial_categories 
                                        WHERE  initial_categories.id=category_id 
                                        UNION ALL 
                                        SELECT remaining_categories.id 
                                        FROM   recursive_categories 
                                        JOIN   categories AS remaining_categories 
                                        ON     recursive_categories.id=remaining_categories.parent_id )
                          SELECT   id 
                          FROM     recursive_categories ) 
ORDER BY updated_at DESC limit 1; 
return recentThreadId;
end

然后我在select语句中调用函数

SELECT outer_categories.*, recently_active_thread(outer_categories.id)
FROM categories AS outer_categories
WHERE outer_categories.parent_id IS NULL 
  AND outer_categories.group_category_id IN (1, 2, 3, 4, 5, 6, 7, 8)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多