如何在同一语句中组合 like 和 between (laravel 查询 Builder/model)
How to combine like and between in same statement (laravel Query Builder/model)
以下是计算机型号的 HDD 列(我知道它不是存储数据的好格式,但它已经这样存储了)
HDD
4x2TBSATA2
2x2TBSATA2
8x2TBSATA2
4x1TBSATA2
2x120GBSSD
4x480GBSSD
我想从存储在特定范围内的 HDD 列中获取范围,例如,获取 120GB 到 1TB 之间的存储应该输出
4x1TBSATA2
2x120GBSSD
4x480GBSSD
我想知道是否可以在同一语句中组合 like 和 between?
我尝试了以下方法,但没有用。
select * from `server_details` where `HDD` between '%120GB%' and '%10TB%'
select * from `server_details` where `HDD` between "Like '%120GB%'" and "LIKE '%10TB%'"
在数据库中,在 HDD 列中,您不应存储 alpha-numeric 值,例如 120GB、10TB,您应该存储数值,例如 120、10000。请尝试使用以下查询。
$hdds = DB::table('server_details')
->whereBetween('HDD', [120, 10000])
->get();
不能将 between 与通配符查询一起使用。您可能能够编写一个正则表达式来匹配您需要的内容,例如:
select * from `server_details` where `HDD` regexp '1[2-9]\dGB|[2-9]\d\dGB|\dTB|10TB'
但如您所见,这是一个基于您所写内容的非常具体的表达式,每个不同的限制都需要不同的表达式。
有 some python code 可以生成这样的表达式,但没有 PHP 我能找到的代码(使用一些非常基本的谷歌搜索)
另一个解决方案(也是我个人推荐的)是将容量添加为单独的列:
迁移您当前的 table:
class AddCapacityColumnMigration extends Migration {
public function up()
{
Schema::table('computers', function (Blueprint $table) {
$table->bigInt('capacityMB')->nullable();
});
Computer::chunk(100, function ($computers) {
foreach ($computers as $computer) {
if (preg_match('/(\d+)x(\d+)(M|G|T)B/',$computer->HDD,$m) {
$capacity = $m[1];
$capacity *= $m[3] === 'M' ? 1 : ($m[3] === 'G' ? 1000 : 1000000 );
$computer->capacityMB = $capacity * $m[2];
$computer->save();
}
}
});
}
然后您可能想在您的模型中添加一个 creating
和 updating
事件以确保您始终设置新的 capacityMB 列。完成所有这些后,您的查询就很简单了:
select * from `server_details` where `capacityMB` between 120000 and 10000000
如果只需要在SQL中做,提取尺寸部分,将其转换为数字,然后进行比较。
select *,
cast(`HDD` as unsigned)*
cast(substr(`HDD`,LOCATE('x',`HDD`)+1) as unsigned)*
(case when`HDD` LIKE '%TB%' then 1000 else 1 end) as GB
from `server_details`
where
cast(`HDD` as unsigned)*
cast(substr(`HDD`,LOCATE('x',`HDD`)+1) as unsigned)*
(case when`HDD` LIKE '%TB%' then 1000 else 1 end)
between 120 and 10000;
以下是计算机型号的 HDD 列(我知道它不是存储数据的好格式,但它已经这样存储了)
HDD
4x2TBSATA2
2x2TBSATA2
8x2TBSATA2
4x1TBSATA2
2x120GBSSD
4x480GBSSD
我想从存储在特定范围内的 HDD 列中获取范围,例如,获取 120GB 到 1TB 之间的存储应该输出
4x1TBSATA2
2x120GBSSD
4x480GBSSD
我想知道是否可以在同一语句中组合 like 和 between?
我尝试了以下方法,但没有用。
select * from `server_details` where `HDD` between '%120GB%' and '%10TB%'
select * from `server_details` where `HDD` between "Like '%120GB%'" and "LIKE '%10TB%'"
在数据库中,在 HDD 列中,您不应存储 alpha-numeric 值,例如 120GB、10TB,您应该存储数值,例如 120、10000。请尝试使用以下查询。
$hdds = DB::table('server_details')
->whereBetween('HDD', [120, 10000])
->get();
不能将 between 与通配符查询一起使用。您可能能够编写一个正则表达式来匹配您需要的内容,例如:
select * from `server_details` where `HDD` regexp '1[2-9]\dGB|[2-9]\d\dGB|\dTB|10TB'
但如您所见,这是一个基于您所写内容的非常具体的表达式,每个不同的限制都需要不同的表达式。
有 some python code 可以生成这样的表达式,但没有 PHP 我能找到的代码(使用一些非常基本的谷歌搜索)
另一个解决方案(也是我个人推荐的)是将容量添加为单独的列:
迁移您当前的 table:
class AddCapacityColumnMigration extends Migration {
public function up()
{
Schema::table('computers', function (Blueprint $table) {
$table->bigInt('capacityMB')->nullable();
});
Computer::chunk(100, function ($computers) {
foreach ($computers as $computer) {
if (preg_match('/(\d+)x(\d+)(M|G|T)B/',$computer->HDD,$m) {
$capacity = $m[1];
$capacity *= $m[3] === 'M' ? 1 : ($m[3] === 'G' ? 1000 : 1000000 );
$computer->capacityMB = $capacity * $m[2];
$computer->save();
}
}
});
}
然后您可能想在您的模型中添加一个 creating
和 updating
事件以确保您始终设置新的 capacityMB 列。完成所有这些后,您的查询就很简单了:
select * from `server_details` where `capacityMB` between 120000 and 10000000
如果只需要在SQL中做,提取尺寸部分,将其转换为数字,然后进行比较。
select *,
cast(`HDD` as unsigned)*
cast(substr(`HDD`,LOCATE('x',`HDD`)+1) as unsigned)*
(case when`HDD` LIKE '%TB%' then 1000 else 1 end) as GB
from `server_details`
where
cast(`HDD` as unsigned)*
cast(substr(`HDD`,LOCATE('x',`HDD`)+1) as unsigned)*
(case when`HDD` LIKE '%TB%' then 1000 else 1 end)
between 120 and 10000;