libern/clickhouse-builder

Clickhouse sql查询构建器

1.0.7 2018-06-11 12:29 UTC

This package is auto-updated.

Last update: 2024-09-09 04:22:53 UTC


README

Build Status Coverage Status

要求

php 7.1

安装

通过composer

composer require esazykin/clickhouse-builder

使用

对于工作的查询构建器,我们必须先前实例化并在构造函数中传递 the-tinderbox/clickhouse-php-client

$server = new Tinderbox\Clickhouse\Server('127.0.0.1', '8123', 'default', 'user', 'pass');
$client = new Tinderbox\Clickhouse\Client($server);
$builder = new Builder($client);

之后我们可以构建和执行sql查询。

选择列

$builder->select('column', 'column2', 'column3 as alias');
$builder->select(['column', 'column2', 'column3 as alias']);
$builder->select(['column', 'column2', 'column3' => 'alias']);

所有这些调用将被转换为以下sql

SELECT `column`, `column2`, `column3` AS `alias` 

此外,作为列,我们可以传递闭包。在这种情况下,闭包将传递Column类的实例,在其中我们可以设置列如何使用。这可以用于具有许多函数、子查询等的复杂表达式。

$builder->select(function ($column) {
    $column->name('time')->sumIf('time', '>', 10); 
});

将被编译成

SELECT sumIf(`time`, time > 10) 
$builder->select(function ($column) {
    $column->as('alias') //or ->name('alias') in this case
    ->query()
    ->select('column')
    ->from('table'); 
});

将被编译成

SELECT  (SELECT `column` FROM `table) as `alias`

也可以通过以下任何一种方法实现相同的行为

$1 = $builder->select(function ($column) {
         $column->as('alias') //or ->name('alias') in this case
            ->query(function ($query) {
                $query->select('column')->from('table');
            })
});
$2 = $builder->select(function ($column) {
         $column->as('alias') //or ->name('alias') in this case
            ->query($builder->select('column')->from('table')); 
});

注意!列上的函数不稳定,处于开发中。

$builder->select('column')->from('table', 'alias');

生成以下查询

SELECT `column` FROM `table` as `alias` 

也可以传递闭包或构建器作为参数执行子查询。

$builder->from(function ($from) {
    $from->query()->select('column')->from('table');
});
SELECT * FROM (SELECT `column` FROM `table`) 

$builder->from(function ($from) {
    $from->query(function ($query) {
        $query->select('column')->from('table');
    });
});

$builder->from(function ($from) {
    $from->query($builder->select('column')->from('table'));
});

$builder->from($builder->select('column')->from('table'));

这是上面列出的相同sql查询的所有变体。

样本系数

$builder->select('column')->from('table')->sample(0.1);
SELECT `column` FROM `table` SAMPLE 0.1 

我认为不需要额外的文字)

连接

$builder->from('table')->join('another_table', 'any', 'left', ['column1', 'column2'], true);
SELECT * FROM `table` GLOBAL ANY LEFT JOIN `another_table` USING `column1`, `column2` 

要作为第一个参数执行子查询,您可以传递闭包或构建器。

$builder->from('table')->join(function ($query) {
    $query->select('column1', 'column2')->from('table2');
}, 'any', 'left', ['column1', 'column2']);

$builder->from('table')->join($builder->select('column1', 'column2')->from('table2'), 'any', 'left', ['column1', 'column2']);
SELECT * FROM `table` ANY LEFT JOIN (SELECT `column1`, `column2` FROM `table2`) USING `column1`, `column2` 

还有许多具有硬编码参数的辅助函数,例如严格或类型及其组合。

$builder->from('table')->anyLeftJoin('table', ['column']);
$builder->from('table')->allLeftJoin('table', ['column']);
$builder->from('table')->allInnerJoin('table', ['column']);
$builder->from('table')->anyInnerJoin('table', ['column']);

$buulder->from('table')->leftJoin('table', 'any', ['column']);
$buulder->from('table')->innerJoin('table', 'all', ['column']);

临时表的使用

在某些情况下,您需要根据它们的id过滤用户,但id的数量很大。您可以存储用户id到本地文件,上传到服务器,并将其用作临时表。

/*
 * Add file with users ids to builder as _users table
 * Also, we must define data structure in file. In example below
 * structure will be like ['UInt64']
 */
$builder->addFile('users.csv', '_users', ['UInt64']);
$builder->select(raw('count()'))->from('clicks')->whereIn('userId', new Identifier('_users'));

将生成

SELECT count() FROM `clicks` WHERE `userId` IN `_users`

如果您希望自动检测表,请在调用 whereIn 之前调用 addFile 方法。

您可以在查询构建器的 whereInprewhereInhavingInjoin 语句中使用本地文件。

Prewhere、where、having

所有示例都将关于where,但对于prewhere和having也有相同的行为。

$builder->from('table')->where('column', '=', 'value');
$builder->from('table')->where('column', 'value');
SELECT * FROM `table` WHERE `column` = 'value' 

所有字符串值都将用单引号括起来。如果没有提供运算符,则使用 =。如果没有提供运算符并且值是数组,则使用 IN

$builder->from('table')->where(function ($query) {
    $query->where('column1', 'value')->where('column2', 'value');
});
SELECT * FROM `table` WHERE (`column1` = 'value' AND `column2` = 'value') 

如果第一个参数传递了闭包,则所有where语句将用括号括起来。但如果在该构建器(在闭包内部)指定了 from,则它将被转换为子查询。

$builder->from('table')->where(function ($query) {
    $query->select('column')->from('table');
})
SELECT * FROM `table` WHERE (SELECT `column` FROM `table`) 

值参数几乎相同,除了用括号括起来。任何传递给值参数的闭包或构建器实例都将转换为子查询。

$builder->from('table')->where('column', 'IN', function ($query) {
    $query->select('column')->from('table');
});
SELECT * FROM `table` WHERE `column` IN (SELECT `column` FROM `table`) 

您还可以传递该语句的内部表示,它将被使用。我将不会深入解释这一点,因为这不是首选的使用方式。

像连接一样,有许多具有硬编码参数的辅助函数。

$builder->where();
$builder->orWhere();

$builder->whereRaw();
$builer->orWhereRaw();

$builder->whereIn();
$builder->orWhereIn();

$builder->whereGlobalIn();
$builder->orWhereGlobalIn();

$builder->whereGlobalNotIn();
$builder->orWhereGlobalNotIn();

$builder->whereNotIn();
$builder->orWhereNotIn();

$builder->whereBetween();
$builder->orWhereBetween();

$builder->whereNotBetween();
$builder->orWhereNotBetween();

$builder->whereBetweenColumns();
$builder->orWhereBetweenColumns();

$builder->whereNotBetweenColumns();
$builder->orWhereNotBetweenColumns();

还有方法通过字典创建where

$builder->whereDict('dict', 'attribute', 'key', '=', 'value');
SELECT dictGetString('dict', 'attribute', 'key') as `attribute` WHERE `attribute` = 'value' 

如果您想使用复杂的键,可以传递一个数组作为 $key,然后数组将转换为元组。默认情况下,所有字符串都将用单引号转义,但您可以传递一个 Identifier 实例来传递,例如列名

$builder->whereDict('dict', 'attribute', [new Identifier('column'), 'string value'], '=', 'value');

将生成

SELECT dictGetString('dict', 'attribute', tuple(`column`, 'string value')) as `attribute` WHERE `attribute` = 'value' 

Group By

与select的行为相同。

$builder->from('table')->select('column', raw('count()')->groupBy('attribute');

最终查询将如下所示

SELECT `column`, count() FROM `table` GROUP BY `attribute`

Order By

$builder->from('table')->orderBy('column', 'asc', 'fr');

在上面的示例中,第三个参数是可选的

SELECT *  FROM `table` ORDER BY `column` ASC COLLATE 'fr'

别名

$builder->orderByAsc('column');
$builder->orderByDesc('column');

对于列,其行为与select方法中的行为相同。

Limit

有两种类型的limit。Limit和limit n by。

Limit n by

$builder->from('table')->limitBy(1, 'column1', 'column2');

将生成

SELECT * FROM `table` LIMIT 1 BY `column1`, `column2` 

简单limit

$builder->from('table')->limit(10, 100);

将生成

SELECT * FROM `table` LIMIT 100, 10 
$builder->from('table')->limit(10, 100);

SELECT * FROM `table` LIMIT 100, 10

Union ALL

unionAll 方法中可以传入闭包或构建器实例。如果是闭包内部会传入构建器实例。

$builder->from('table')->unionAll(function($query) {
    $query->select('column1')->from('table');
})->unionAll($builder->select('column2')->from('table'));
SELECT * FROM `table` UNION ALL SELECT `column1` FROM `table` UNION ALL SELECT `column2` FROM `table` 

执行请求并获取结果。

在构建请求后,必须调用 get() 方法以将请求发送到服务器。此外,还有机会进行异步请求。它的工作方式几乎与 unionAll 相同。

$builder->from('table')->asyncWithQuery(function($query) {
    $query->from('table');
});
$builder->from('table')->asyncWithQuery($builder->from('table'));
$builder->from('table')->asyncWithQuery()->from('table');

这些调用会产生相同的行为。将异步执行两个查询。现在,如果您调用 get() 方法,结果将返回一个数组,其中数值索引对应于该数字请求的结果。