Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQL 优化记录 #203

Open
yaogengzhu opened this issue Feb 19, 2024 · 0 comments
Open

SQL 优化记录 #203

yaogengzhu opened this issue Feb 19, 2024 · 0 comments

Comments

@yaogengzhu
Copy link
Owner

我写的

async function getTeamList(req, res) {
  const { user } = req;
  let { page, pageSize } = req.body;
  page = page || 1;
  pageSize = pageSize || 10;
  try {
    // 查询1: 团队总数
    const total = await knex('user')
      .count('* as total')
      .where('parent_id', req.user.id);
    // 查询2: 今日新增
    const today = await knex('user')
      .count('* as today')
      .where('parent_id', req.user.id)
      .whereRaw('DATE(created_at) = DATE(NOW())');
    // 查询3: 昨日新增
    const yesterday = await knex('user')
      .count('* as yesterday')
      .where('parent_id', req.user.id)
      .whereRaw('DATE(created_at) = DATE(NOW() - INTERVAL 1 DAY)');
    // 查询4: 本月新增
    const thisMonth = await knex('user')
      .count('* as this_month')
      .where('parent_id', req.user.id)
      .whereRaw(
        'MONTH(created_at) = MONTH(NOW()) AND YEAR(created_at) = YEAR(NOW())',
      );
    const teamInfo = {
      total: total[0].total,
      today: today[0].today,
      yesterday: yesterday[0].yesterday,
      thisMonth: thisMonth[0].this_month,
    };
    // 查询5: 团队列表
    const result = await knex('user')
      .select('*')
      .where('parent_id', user.id)
      .limit(pageSize)
      .offset((page - 1) * pageSize);
    if (result.length != 0) {
      for (let i = 0; i < result.length; i++) {
        // 查询7天内拉新
        const sevenDay = await knex('user')
          .count('* as count')
          .where('parent_id', result[i].id)
          .whereRaw('created_at > DATE_SUB(NOW(), INTERVAL 7 DAY)');
        result[i].sevenDay = sevenDay[0].count;
        // 七天出单
        const sevenDayOrder = await knex('sys_orders as so')
          .join('command_task as ct', 'ct.command_id', 'so.command_id')
          .count('* as count')
          .where('ct.user_id', result[i].id)
          .whereRaw('so.pay_time > DATE_SUB(NOW(), INTERVAL 7 DAY)');
        result[i].sevenDayOrder = sevenDayOrder[0].count;
      }
    }
    res.send({
      code: 0,
      message: 'ok',
      data: result,
      teamInfo,
    });
  } catch (e) {
    res.send({
      code: 1,
      message: '获取团队列表失败',
    });
    logger.info(e);
  }
}

优化的语句

async function getTeamList(req, res) {
  let { page, pageSize } = req.body;
  page = page || 1;
  pageSize = pageSize || 10;

  // 提取重复的查询条件
  const parentIdCondition = { parent_id: req.user.id };

  try {
    const [total, today, yesterday, thisMonth, result] = await Promise.all([
      // 查询1: 团队总数
      knex('user').count('* as total').where(parentIdCondition),

      // 查询2: 今日新增
      knex('user')
        .count('* as today')
        .where(parentIdCondition)
        .whereRaw('DATE(created_at) = DATE(NOW())'),

      // 查询3: 昨日新增
      knex('user')
        .count('* as yesterday')
        .where(parentIdCondition)
        .whereRaw('DATE(created_at) = DATE(NOW() - INTERVAL 1 DAY)'),

      // 查询4: 本月新增
      knex('user')
        .count('* as this_month')
        .where(parentIdCondition)
        .whereRaw(
          'MONTH(created_at) = MONTH(NOW()) AND YEAR(created_at) = YEAR(NOW())',
        ),

      // 查询5: 团队列表
      knex('user')
        .select('*')
        .where(parentIdCondition)
        .limit(pageSize)
        .offset((page - 1) * pageSize),
    ]);

    const teamInfo = {
      total: total[0].total,
      today: today[0].today,
      yesterday: yesterday[0].yesterday,
      thisMonth: thisMonth[0].this_month,
    };

    if (result.length !== 0) {
      const userIds = result.map((user) => user.id);
      // 查询7天内拉新和7天出单
      const [sevenDayCounts, sevenDayOrderCounts] = await Promise.all([
        knex('user')
          .select('parent_id')
          .count('* as count')
          .whereIn('parent_id', userIds)
          .whereRaw('created_at > DATE_SUB(NOW(), INTERVAL 7 DAY)')
          .groupBy('parent_id'),

        knex('sys_orders as so')
          .join('command_task as ct', 'ct.command_id', 'so.command_id')
          .select('ct.user_id')
          .count('* as count')
          .whereIn('ct.user_id', userIds)
          .whereRaw('so.pay_time > DATE_SUB(NOW(), INTERVAL 7 DAY)')
          .groupBy('ct.user_id'),
      ]);

      const sevenDayMap = new Map(
        sevenDayCounts.map((item) => [item.parent_id, item.count]),
      );
      const sevenDayOrderMap = new Map(
        sevenDayOrderCounts.map((item) => [item.user_id, item.count]),
      );

      result.forEach((user) => {
        user.sevenDay = sevenDayMap.get(user.id) || 0;
        user.sevenDayOrder = sevenDayOrderMap.get(user.id) || 0;
      });
    }

    res.send({
      code: 0,
      message: 'ok',
      data: result,
      teamInfo,
    });
  } catch (e) {
    res.send({
      code: 1,
      message: '获取团队列表失败',
    });
    logger.info(e);
  }
}

总结:
这里我们使用了 Promise.all 来并行执行多个查询,这样可以减少总的查询时间。同时,我们将查询7天内拉新和7天出单的操作合并为一个查询,并使用 Map 对象来存储结果,以便在后续的循环中快速查找。

注意:这里的优化主要是减少了查询次数,但实际上查询效率还是取决于数据库的性能和表的索引设置。如果查询仍然很慢,建议检查数据库性能和索引配置。

@yaogengzhu yaogengzhu changed the title SQL记录 SQL 优化记录 Feb 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant