【问题标题】:N1QL Multiple join and sum query producing wrong outputN1QL 多连接和求和查询产生错误输出
【发布时间】:2019-10-30 08:07:14
【问题描述】:

我有一个包含以下三个文档的存储桶:

coffee {
    id
}

cold_coffee {
    coffeeId
    number
}

warm_coffee {
    coffeeId
    number
}

我使用 Couchbase Server Community Edition 6.0.0 在 N1QL 中编写了以下查询:

SELECT META(coffee).id as coffeeId,
SUM(cold_coffee.`number`) as `ccNumber`,
SUM(warm_coffee.`number`) as `wcNumber`,
FROM coffee_bucket coffee
left JOIN coffee_bucket cold_coffee
    ON  META(coffee).id = cold_coffee.coffeeId 
    and cold_coffee.type='cold_coffee'
left JOIN coffee_bucket warm_coffee
    ON META(coffee).id = warm_coffee.coffeeId 
    and warm_coffee.type='warm_coffee'
where coffee.type='coffee'
group by META(coffee).id;

每份咖啡都有多个cold_coffee 和warm_coffee 文档,我需要对所有cold_coffee 和warm_coffee 文档的数字求和。我遇到的问题是,例如,如果我有以下文件:

[
    coffee {
        id: 1
    },
    cold_coffee {
        coffeeId:1
        number:5 
    },
    cold_coffee {
        coffeeId:1
        number:5 
    },
    warm_coffee {
        coffeeId:1
        number:10
    }
]

我的总数如下:

ccNumber: 10
wcNumber:20 

似乎是因为加入,单个 warm_coffee 文档被计算了两次?

我遇到了这个site,可能有同样的错误,但不幸的是它是 SQL。

我不确定如何使用 N1QL 解决这个问题,因为 JOIN 的右手术语必须是表/存储桶,如下面的post 所示。

这是一个可能的solution,但我不确定如何实现这是 N1QL?

有人可以帮忙吗?

【问题讨论】:

    标签: couchbase n1ql


    【解决方案1】:

    JOINS 可以扩展原始行。在第一次加入时,最左边的文档被展开。您正在使用第一个文档字段作为第二个连接条件,可以生成多个文档相同的条件。这就是语义的工作方式。您需要根据需要调整您的加入条件。

    第二个 JOIN 最多使用 LEFT 中的一个文档。 SUM over DISTINCT 可能不起作用,因为不同文档的相同值(warm_coffee,可能计数不足)只计算一次。如果我是对的,您正在寻找第二次加入,以使用来自 LEFT 大多数咖啡的独特文档。

    也许你正在寻找类似的东西

    SELECT c.coffeeId,
           MAX(c.ccNumber) AS `ccNumber`,
           SUM(warm_coffee.`number`) AS `wcNumber`,
    FROM ( SELECT META(coffee).id AS coffeeId,
           SUM(cold_coffee.`number`) AS `ccNumber`
           FROM coffee_bucket coffee
           LEFT JOIN coffee_bucket cold_coffee
                ON  META(coffee).id = cold_coffee.coffeeId AND cold_coffee.type='cold_coffee'
           WHERE coffee.type='coffee'
           GROUP BY META(coffee).id
         ) AS c
    LEFT JOIN coffee_bucket warm_coffee
              ON c.coffeeId = warm_coffee.coffeeId AND warm_coffee.type='warm_coffee'
    GROUP BY c.coffeeId;
    

    三级加入

    SELECT d.coffeeId,
           MAX(c.ccNumber) AS `ccNumber`,
           MAX(c.wcNumber) AS `wcNumber`,
           SUM(ch.`number`) AS `chNumber`
    FROM ( SELECT c.coffeeId,
                  MAX(c.ccNumber) AS `ccNumber`,
                  SUM(warm_coffee.`number`) AS `wcNumber`,
           FROM ( SELECT META(coffee).id AS coffeeId,
                  SUM(cold_coffee.`number`) AS `ccNumber`
                  FROM coffee_bucket coffee
                  LEFT JOIN coffee_bucket cold_coffee
                       ON  META(coffee).id = cold_coffee.coffeeId AND cold_coffee.type='cold_coffee'
                  WHERE coffee.type='coffee'
                  GROUP BY META(coffee).id
                ) AS c
           LEFT JOIN coffee_bucket warm_coffee
                     ON c.coffeeId = warm_coffee.coffeeId AND warm_coffee.type='warm_coffee'
           GROUP BY c.coffeeId) AS d
    LEFT JOIN coffee_bucket ch
         ON d.coffeeId = ch.coffeeId AND ch.type='chaoc_coffee'
    GROUP BY d.coffeeId
    ;
    

    【讨论】:

    • 太棒了!非常感谢您的帮助!如果添加了另一个文件,例如 choc_coffee,并且所有这些文件都需要一笔款项,您能否提供建议?我很难理解如何将该逻辑添加到您的解决方案中?谢谢!
    • 顺便说一句,如果这两个文件需要总和,则此代码有效
    • 查看 3 级连接。相关子查询需要使用键。否则,使用相关子查询会更容易
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多