【问题标题】:Laravel - WhereRaw CAST query not working within while loopLaravel - WhereRaw CAST 查询在 while 循环中不起作用
【发布时间】:2020-02-01 15:10:41
【问题描述】:

我有一个 SQL 查询,我将列转换为 SIGNED 以将其与整数进行比较。我的表“行星”如下所示

id | name | galaxy | region
1  | S1   | 00     | 01
2  | S2   | 00     | 01
3  | S3   | 00     | 02
4  | S4   | 01     | 00
5  | S5   | 00     | 00

有数百个条目属于不同的星系 (0-99) 和区域 (0-99)

galaxy 和 region 列设置为字符串,以使用前导 0 存储它们。也许不是最好的方法,但我就是这样做的。

我有一个变量如下

$planet = Planet::where('galaxy', '00')->get();

然后我有下面的循环来带出属于 00 星系和定义区域的行星,循环穿过每个可能的区域 (0 - 99) 并打印计数。

$count = 0;
while($count < 100){

   echo $planet->whereRaw('CAST(region as SIGNED) = '.$count)->count();

   $count++;
}

问题是,第一次交互(其中 $count 等于 0)返回结果,但任何后续循环都不会返回任何内容。如果我将 $count 设置为不同的值,则相同的故事 - 第一个循环有效,但以下循环均无效。

非常感谢任何关于为什么会出现这种情况的想法。我在循环中回显了 $count 以仔细检查它肯定会按顺序打印 0 到 99 之间的数字,而且确实如此,所以不确定为什么它没有在 SQL 查询中返回第一个以外的结果。

编辑:我想要达到的目标如下图所示:

基本上有成千上万的行星,每一个都在一个星系和一个区域中。星系编号 00-99 和区域。

我将转到/map/00 的网址,告诉我我正在查看哪个星系,然后会有上面 10 x 10 的网格,每个部分都包含该星系该区域中行星的数量。每个网格都是在 while 循环中创建的 div。

所以实际的 while 循环如下所示:

$count = 0;
    while($count < 100){
       echo "<div class="inline-flex w-1/10">
       echo $planet->whereRaw('CAST(region as SIGNED) = '.$count)->count();
       echo "</div>
       $count++;
    }

计数已到位,因此我们知道我们在网格的哪个部分,因此过滤 $astros->whereRaw 查询以专注于该区域。因为实际表是字符串而不是整数,所以我需要将 is 作为 SIGNED 字段进行转换,以便 where 查询起作用。所以我实际追求的SQL查询如下:

SELECT * FROM planets WHERE galaxy = 00 AND CAST(region as SIGNED) = $count

【问题讨论】:

  • 欢迎@Jake!什么$astros
  • 对不起,astros 实际上是 $planet 所以这就是我之前提到的查询 $planet = Planet::where('galaxy','00')->get();只是一个错字,对不起!已更正。

标签: php sql laravel while-loop casting


【解决方案1】:

问题 #1:集合

你不能使用whereRaw(),因为$planet是集合,因为使用了-&gt;get()

$planet = Planet::where('galaxy', '00')->get(); // collection

问题 #2:AND、AND、AND、...

当你使用$planet而不使用-&gt;get()时,你会得到很多where的组合。

$planet = Planet::where('galaxy', '00');
$count = 0;

while($count < 100){
   echo $planet->whereRaw('CAST(region as SIGNED) = '. $count)->count();

   $count++;
}

结果

select * from `planets` where (`galaxy` = ?) and CAST(region as SIGNED) = 0

select * from `planets` where (`galaxy` = ?) and CAST(region as SIGNED) = 0 and CAST(region as SIGNED) = 1

select * from `planets` where (`galaxy` = ?) and CAST(region as SIGNED) = 0 and CAST(region as SIGNED) = 1 and CAST(region as SIGNED) = 2

select * from `planets` where (`galaxy` = ?) and CAST(region as SIGNED) = 0 and CAST(region as SIGNED) = 1 and CAST(region as SIGNED) = 2 and CAST(region as SIGNED) = 3

select * from `planets` where (`galaxy` = ?) and CAST(region as SIGNED) = 0 and CAST(region as SIGNED) = 1 and CAST(region as SIGNED) = 2 and CAST(region as SIGNED) = 3 and CAST(region as SIGNED) = 4

select * from `planets` where (`galaxy` = ?) and CAST(region as SIGNED) = 0 and CAST(region as SIGNED) = 1 and CAST(region as SIGNED) = 2 and CAST(region as SIGNED) = 3 and CAST(region as SIGNED) = 4 and CAST(region as SIGNED) = 5

....

select * from `planets` where (`galaxy` = ?) and CAST(region as SIGNED) = 0 and CAST(region as SIGNED) = 1 and CAST(region as SIGNED) = 2 and CAST(region as SIGNED) = 3 and CAST(region as SIGNED) = 4 and CAST(region as SIGNED) = 5 and CAST(region as SIGNED) = 6 and CAST(region as SIGNED) = 7 and CAST(region as SIGNED) = 8 and CAST(region as SIGNED) = 9 and CAST(region as SIGNED) = 10 and CAST(region as SIGNED) = 11 and CAST(region as SIGNED) = 12 and CAST(region as SIGNED) = 13 and CAST(region as SIGNED) = 14 and CAST(region as SIGNED) = 15 and CAST(region as SIGNED) = 16 and CAST(region as SIGNED) = 17 and CAST(region as SIGNED) = 18 and CAST(region as SIGNED) = 19 and CAST(region as SIGNED) = 20 and CAST(region as SIGNED) = 21 and CAST(region as SIGNED) = 22 and CAST(region as SIGNED) = 23 and CAST(region as SIGNED) = 24 and CAST(region as SIGNED) = 25 and CAST(region as SIGNED) = 26 and CAST(region as SIGNED) = 27 and CAST(region as SIGNED) = 28 and CAST(region as SIGNED) = 29 and CAST(region as SIGNED) = 30 and CAST(region as SIGNED) = 31 and CAST(region as SIGNED) = 32 and CAST(region as SIGNED) = 33 and CAST(region as SIGNED) = 34 and CAST(region as SIGNED) = 35 and CAST(region as SIGNED) = 36 and CAST(region as SIGNED) = 37 and CAST(region as SIGNED) = 38 and CAST(region as SIGNED) = 39 and CAST(region as SIGNED) = 40 and CAST(region as SIGNED) = 41 and CAST(region as SIGNED) = 42 and CAST(region as SIGNED) = 43 and CAST(region as SIGNED) = 44 and CAST(region as SIGNED) = 45 and CAST(region as SIGNED) = 46 and CAST(region as SIGNED) = 47 and CAST(region as SIGNED) = 48 and CAST(region as SIGNED) = 49 and CAST(region as SIGNED) = 50 and CAST(region as SIGNED) = 51 and CAST(region as SIGNED) = 52 and CAST(region as SIGNED) = 53 and CAST(region as SIGNED) = 54 and CAST(region as SIGNED) = 55 and CAST(region as SIGNED) = 56 and CAST(region as SIGNED) = 57 and CAST(region as SIGNED) = 58 and CAST(region as SIGNED) = 59 and CAST(region as SIGNED) = 60 and CAST(region as SIGNED) = 61 and CAST(region as SIGNED) = 62 and CAST(region as SIGNED) = 63 and CAST(region as SIGNED) = 64 and CAST(region as SIGNED) = 65 and CAST(region as SIGNED) = 66 and CAST(region as SIGNED) = 67 and CAST(region as SIGNED) = 68 and CAST(region as SIGNED) = 69 and CAST(region as SIGNED) = 70 and CAST(region as SIGNED) = 71 and CAST(region as SIGNED) = 72 and CAST(region as SIGNED) = 73 and CAST(region as SIGNED) = 74 and CAST(region as SIGNED) = 75 and CAST(region as SIGNED) = 76 and CAST(region as SIGNED) = 77 and CAST(region as SIGNED) = 78 and CAST(region as SIGNED) = 79 and CAST(region as SIGNED) = 80 and CAST(region as SIGNED) = 81 and CAST(region as SIGNED) = 82 and CAST(region as SIGNED) = 83 and CAST(region as SIGNED) = 84 and CAST(region as SIGNED) = 85 and CAST(region as SIGNED) = 86 and CAST(region as SIGNED) = 87 and CAST(region as SIGNED) = 88 and CAST(region as SIGNED) = 89 and CAST(region as SIGNED) = 90 and CAST(region as SIGNED) = 91 and CAST(region as SIGNED) = 92 and CAST(region as SIGNED) = 93 and CAST(region as SIGNED) = 94 and CAST(region as SIGNED) = 95 and CAST(region as SIGNED) = 96 and CAST(region as SIGNED) = 97 and CAST(region as SIGNED) = 98 and CAST(region as SIGNED) = 99

解决方案 #1

$count = 0;

while ($count < 100) {
    $total = Planet::where('galaxy', '00')
        ->whereRaw('CAST(region as SIGNED) = ' . $count)
        ->count();

    echo $total;

    $count++;
}

结果

+--------+-------+
| Region | Count |
+--------+-------+
| 00     | 1     |
| 01     | 2     |
| 02     | 1     |
| 03     | 0     |
| 04     | 0     |

....

| 99     | 0     |
+--------+-------+

解决方案 #1(最佳方式,单个查询)

$planets = Planet::select('region', \DB::raw('count(*) as total'))
    ->where('galaxy', '00')
    ->groupBy('region')
    ->pluck('total', 'region');

结果

# region => total
array:3 [
    "00" => 1
    "01" => 2
    "02" => 1
]

【讨论】:

  • 太棒了,非常感谢。我可以问一下,我试图从原始 $planet 变量中删除 ->get() 并且没有任何区别,是因为它仍然会尝试在每个循环中附加 whereRaw() 吗?再次感谢!
  • @Jake 是的。您可以通过将get()更改为tosql()来检查SQL查询
猜你喜欢
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-11
  • 2011-10-19
  • 1970-01-01
  • 2015-08-02
相关资源
最近更新 更多