【问题标题】:N1ql Join and aggregate with additional valuesN1ql 加入和聚合附加值
【发布时间】:2020-09-19 23:17:32
【问题描述】:

我有一个包含以下文档的存储桶(Couchbase 社区版 6.5):

employees {
    employeeGroupId: string,
    type: "Employee"
}
clocks {
    employeeId: string,
    areaId: string
    date: string,
    type: "Clock"
}

每个员工每天都有多个对应的时钟项目。我需要得到以下信息:

  1. 第一个时钟 -> 时钟输入
  2. 最后一个时钟 -> 时钟输出

我编写了以下查询,它获取执行时间

SELECT META(employee).id AS employeeId,
       employee.employeeGroupId,
       MIN(clock.date) AS clockIn,
       MAX(clock.date) AS clockOut
FROM `bucket` employee LEFT
    JOIN `bucket` clock ON clock.employeeId = META(employee).id
    AND type = "Clock"
    AND clock.date BETWEEN "2020-06-01T00:00:00.000Z" AND "2020-06-02T00:00:00.000Z"
WHERE employee.type = "Employee"
GROUP BY employee;

问题是我需要用匹配的时钟来获取对应的areaId。

我已经编写了以下查询。我创建了两个单独的子查询,对当天的所有时钟项进行排序,先升序然后降序,然后选择第一项。

CREATE INDEX adv_employeeId_type_date_blockId ON `bucket`(`employeeId`,`type`,`date`,`blockId`)        
CREATE INDEX adv_employeeId_type_date ON `bucket`(`employeeId`,`type`,`date`)
CREATE INDEX adv_type_employeeId_date ON `bucket`(`type`,`employeeId`,`date`)

SELECT META(employee).id AS employeeId,
       employee.employeeGroupId,
       clockIn,
       clockOut
FROM `bucket` employee 
    LEFT JOIN (
    SELECT obj.employeeId,
           obj.date,
           obj.areaId
    FROM `bucket` obj
    WHERE obj.employeeId = META(employee).id
        AND obj.type = "Clock"
        AND obj.date BETWEEN "2020-06-01T00:00:00.000Z" AND "2020-06-02T00:00:00.000Z"
    ORDER BY obj.date
    LIMIT 1) clockIn ON clockIn.employeeId = META(employee).id 
    LEFT JOIN (
    SELECT obj.employeeId,
           obj.date,
           obj.areaId
    FROM `bucket` obj
    WHERE obj.employeeId = META(employee).id
        AND obj.type = "Clock"
        AND obj.date BETWEEN "2020-06-01T00:00:00.000Z" AND "2020-06-02T00:00:00.000Z"
    ORDER BY obj.date DESC
    LIMIT 1) clockOut ON clockOut.employeeId = META(employee).id
WHERE employee.type = "Employee"
GROUP BY employee,
         clockIn,
         clockOut;

问题是上述查询效率低,执行时间>10秒。

换句话说,我需要从聚合的 MIN() 和 MAX() 函数中获取额外的对象值。

我确信第二个查询不是实现这一目标的最有效方法,还有其他建议吗?

【问题讨论】:

    标签: performance join couchbase n1ql


    【解决方案1】:
    CREATE INDEX ix1 ON `bucket`(type, `employeeGroupId`) WHERE type = "Employee";
    CREATE INDEX ix2 ON `bucket`(`employeeId`, date, areaId) WHERE type = "Clock";
    
    SELECT META(employee).id AS employeeId,
           employee.employeeGroupId,
           minclock[0] AS clockIn,
           minclock[1] AS clockInAreaId,
           maxclock[0] AS clockOut,
           maxclock[1] AS clockOutAreaId
    FROM `bucket` AS employee LEFT
        JOIN `bucket` AS clock ON clock.employeeId = META(employee).id
        AND type = "Clock"
        AND clock.date BETWEEN "2020-06-01T00:00:00.000Z" AND "2020-06-02T00:00:00.000Z"
    WHERE employee.type = "Employee"
    GROUP BY employee
    LETTING minclock = MIN([clock.date,clock.areaId]),
            maxclock = MAX([clock.date,clock.areaId]);
    

    SELECT META(employee).id AS employeeId,
           employee.employeeGroupId,
           MIN([clock.date, {clock.date, clock.areaId}])[1] AS clockIn,
           MAX([clock.date, {clock.date, clock.areaId}])[1] AS clockOut,
    FROM `bucket` AS employee LEFT
        JOIN `bucket` AS clock ON clock.employeeId = META(employee).id
        AND type = "Clock"
        AND clock.date BETWEEN "2020-06-01T00:00:00.000Z" AND "2020-06-02T00:00:00.000Z"
    WHERE employee.type = "Employee"
    GROUP BY employee;
    

    在数组上使用 MIN/MAX。第 0 个表达式是 MIN/MAX 表达式。重置仅用于关系的数组位置(类似于 ORDER BY 多个字段)。结果将完成 ARRAY 表达式。 选择您想要项目的职位。这种技术允许您投影非分组表达式。

    【讨论】:

    • 是否可以在 MIN/MAX 表达式中检查每个时钟文档的条件?例如只对设置了特定标志的时钟文档应用 MIN 函数?
    • 你能否解释一下为什么我的第二个查询比第一个慢得多?
    • 可以使用 CASE 语句。第二个查询很慢,因为它有很多子查询和 JOIN,每个查询都需要获取数据。
    • 为了将来参考,这里是 MIN 函数内的 CASE 语句示例: MIN(CASE WHEN clock.flag = TRUE THEN [clock.date, {clock.date, clock.areaId}]) [1] 作为时钟输入
    猜你喜欢
    • 2021-06-19
    • 2017-10-08
    • 1970-01-01
    • 2019-11-15
    • 2010-11-30
    • 2014-02-19
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    相关资源
    最近更新 更多