【问题标题】:Best way to exclude results from a big db query in Laravel 5.2在 Laravel 5.2 中从大数据库查询中排除结果的最佳方法
【发布时间】:2017-12-07 11:07:40
【问题描述】:

我正在使用 Laravel 5.2 构建大量产品库存,但在显示产品的查询时遇到了问题。示例如下:

我有很多产品——确切地说,在我的数据库中超过 20k。其中大部分我想每天展示,但大约 500-1000 我只需要在一周中的某些日子展示。

目前我已经回顾了以下方法,每种方法都有其缺点:

  1. 创建一个表product_availability,其中每一行将包含product_id、工作日和可用(真/假)列。但是,使用这种结构,我将有 7 行提供 1 个产品的信息,整个表将包含 ~ 140 000 行,我认为这不是一个好主意 - 因为大多数产品每天都可用,而且只有 500 -1000 不会。

  2. 我的第二个猜测是简单地在 products 表中添加一个“可用性”列,该列将包含以下格式的 JSON 字符串:

    {“mo”:“true”,“tu”:“false”,“we”:“false”,“th”:“true”,“fr”:“false”,“sa”:“false” ", "su": "真"}

然后我会这样查询:

$weekday = date('N');
        switch ($weekday) {
            case '1':
                $builder->where('$availability->mo', 'true');
                break;
            case '2':
                $builder->where('$availability->tu', 'true');
                break;
            case '3':
                $builder->where('$availability->we', 'true');
                break;
            case '4':
                $builder->where('$availability->th', 'true');
                break;
            case '5':
                $builder->where('$availability->fr', 'true');
                break;
            case '6':
                $builder->where('$availability->sa', 'true');
                break;
            case '7':
                $builder->where('$availability->su', 'true');
                break;
        }

但这个解决方案的 IMO 问题是它也将是一个缓慢而沉重的方法。

  1. 我的第三个猜测是向后工作,不是检查产品今天是否可用,而是检查哪一天不可用。这样,我将获得所有“可用性”列将为空的产品,并且对于这些产品,它运行一个 if 语句,然后以某种方式添加它们,但我也不知道如何构建它。

所以我的问题是:

什么是获取当今所有可用产品的最快查询,请记住,其中只有一小部分不可用(如何排除它们,也许)?

【问题讨论】:

    标签: php mysql laravel-5 eloquent laravel-5.2


    【解决方案1】:

    我认为您的第一个选项是最好的解决方案(尽管有一些更改)。

    我建议product_availability 的表结构类似于:

    | id | product_id | mon | tue | wed | thu | fri | sat | sun |
    | 1  |      13403 |   1 |   0 |   1 |   0 |   1 |   0 |   0 |
    

    然后你可以查询类似:

    SELECT
      products.*
    FROM
      products
    LEFT JOIN
      product_availability 
    ON
      product_availability.product_id = products.id
    WHERE
      # show if no entry here (i.e. always to be shown)
      product_availability.id IS NULL 
      OR
      # only want to show specific days
      product_availability.id IS NOT NULL AND CASE
        WHEN DAYOFWEEK(CURDATE()) = 1 THEN `sun` = 1
        WHEN DAYOFWEEK(CURDATE()) = 2 THEN `mon` = 1
        WHEN DAYOFWEEK(CURDATE()) = 3 THEN `tue` = 1
        WHEN DAYOFWEEK(CURDATE()) = 4 THEN `wed` = 1
        WHEN DAYOFWEEK(CURDATE()) = 5 THEN `thu` = 1
        WHEN DAYOFWEEK(CURDATE()) = 6 THEN `fri` = 1
        WHEN DAYOFWEEK(CURDATE()) = 7 THEN `sat` = 1
      END
    

    这将显示所有产品。如果product_availability 中有产品 ID 条目,那么它将获取当前星期几(如果您愿意,可以将其替换为其他方法)并查看对应的日期是否有 1 显示。

    其中只有一小部分不可用

    在这种情况下,您只需在product_availability 中添加一个条目。

    这是一个小提琴:http://sqlfiddle.com/#!9/c2bbf1/3

    希望这会有所帮助:)


    编辑:您可以使用一些方法来转换为 eloquent 查询:

      ->leftJoin('product_availability', 'products.id', '=', 'product_availability.product_id')
      ->whereNull('product_availability.id')
      ->orWhere(function ($query) {
        $query
          ->whereRaw('(product_availability.id IS NOT NULL AND CASE
            WHEN DAYOFWEEK(CURDATE()) = 1 THEN `sun` = 1
            WHEN DAYOFWEEK(CURDATE()) = 2 THEN `mon` = 1
            WHEN DAYOFWEEK(CURDATE()) = 3 THEN `tue` = 1
            WHEN DAYOFWEEK(CURDATE()) = 4 THEN `wed` = 1
            WHEN DAYOFWEEK(CURDATE()) = 5 THEN `thu` = 1
            WHEN DAYOFWEEK(CURDATE()) = 6 THEN `fri` = 1
            WHEN DAYOFWEEK(CURDATE()) = 7 THEN `sat` = 1
          END)');
      });
    

    或者你可以只做 DB::raw 查询

    【讨论】:

    • 感谢您的快速答复!小提琴的例子真的很有帮助!如果我理解正确,我们会在 product_availability 中插入一条记录,仅针对非全时可用的产品?
    • 当我使用 laravel 查询时,这样做是不是一个坏主意:->leftJoin('product_availability', 'products.id', '=', 'product_availability.product_id' ) ->whereNull('product_availability.id') ->orWhere(function($query) use ($weekday) { switch ($weekday) { case '1': $query->where('mon', '=' , '1'); break; 考虑到 $weekday 是 (1-7) 并且我对所有 7 种情况都使用 switch?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 2017-06-08
    • 2019-08-27
    相关资源
    最近更新 更多