Where

The where method allows you to filter your query results based on specified conditions.

Use orWhere to create OR conditions between multiple filters.

Use whereGroup and orWhereGroup to create parenthesized groups of conditions.

Basic Usage

import { createQueryBuilder } from '@hypequery/clickhouse';

const db = createQueryBuilder<Schema>();

// Simple where clause
const query = db
  .table('users')
  .where('age', 'gte', 18)
  .toSQL();
// Result: SELECT * FROM users WHERE age >= 18

Type Definitions

where(column: keyof T | TableColumn<Schema>, operator: WhereOperator, value: any): this
where(condition: WhereExpression): this

orWhere(column: keyof T | TableColumn<Schema>, operator: WhereOperator, value: any): this

whereGroup(callback: (builder: this) => void): this
orWhereGroup(callback: (builder: this) => void): this

Parameters

  • column: The column to filter on
  • operator: Comparison operator (eq, neq, gt, gte, lt, lte, like, notLike, in, notIn, between)
  • value: The value to compare against
  • condition: A WhereExpression object
  • callback: A function that receives a WhereBuilder for complex conditions

Returns

Returns the query builder instance for method chaining.

Comparison Operators

OperatorDescriptionExample
eqEqualage = 25
neqNot equalage != 25
gtGreater thanage > 25
gteGreater than or equalage >= 25
ltLess thanage < 25
lteLess than or equalage <= 25
likePattern matchingname LIKE '%john%'
notLikeNot like patternname NOT LIKE '%admin%'
inIn arraystatus IN ('active', 'pending')
notInNot in arraystatus NOT IN ('inactive')
betweenBetween rangeage BETWEEN 18 AND 65

Examples

Simple Conditions

// Equal
db.table('users').where('status', 'eq', 'active')

// Greater than
db.table('users').where('age', 'gt', 18)

// Like pattern
db.table('users').where('name', 'like', '%john%')

// In array
db.table('users').where('status', 'in', ['active', 'pending'])

Multiple Conditions

// Chain multiple where clauses (AND)
const query = db
  .table('users')
  .where('age', 'gte', 18)
  .where('status', 'eq', 'active')
  .where('country', 'eq', 'US')
  .toSQL();
// Result: SELECT * FROM users WHERE age >= 18 AND status = 'active' AND country = 'US'

OR Conditions with orWhere

// Use orWhere for OR conditions
const query = db
  .table('users')
  .where('status', 'eq', 'active')
  .orWhere('role', 'eq', 'admin')
  .orWhere('email', 'like', '%@company.com')
  .toSQL();
// Result: SELECT * FROM users WHERE status = 'active' OR role = 'admin' OR email LIKE '%@company.com'

Mixing AND and OR Conditions

// Combine AND and OR conditions
const query = db
  .table('users')
  .where('age', 'gte', 18)
  .where('country', 'eq', 'US')
  .orWhere('role', 'eq', 'admin')
  .toSQL();
// Result: SELECT * FROM users WHERE age >= 18 AND country = 'US' OR role = 'admin'

Complex Conditions with Groups

// Use whereGroup for parenthesized AND conditions
const query = db
  .table('users')
  .whereGroup((builder) => {
    builder
      .where('age', 'gte', 18)
      .orWhere('parent_consent', 'eq', true);
  })
  .where('status', 'eq', 'active')
  .toSQL();
// Result: SELECT * FROM users WHERE (age >= 18 OR parent_consent = true) AND status = 'active'

Nested Groups

// Complex nested conditions with multiple groups
const query = db
  .table('orders')
  .whereGroup((builder) => {
    builder
      .where('status', 'eq', 'completed')
      .orWhereGroup((innerBuilder) => {
        innerBuilder
          .where('total', 'gte', 100)
          .orWhere('priority', 'eq', 'high');
      });
  })
  .toSQL();
// Result: SELECT * FROM orders WHERE (status = 'completed' OR (total >= 100 OR priority = 'high'))

Date and Time Filtering

import { toDateTime } from '@hypequery/clickhouse';

// Filter by date range
const query = db
  .table('orders')
  .where('created_at', 'gte', toDateTime('2024-01-01'))
  .where('created_at', 'lt', toDateTime('2024-02-01'))
  .toSQL();
// Result: SELECT * FROM orders WHERE created_at >= toDateTime('2024-01-01') AND created_at < toDateTime('2024-02-01')

Array Operations

// Check if array contains value
const query = db
  .table('products')
  .where('tags', 'like', '%electronics%')
  .toSQL();
// Result: SELECT * FROM products WHERE tags LIKE '%electronics%'

// Check if value is in array
const query2 = db
  .table('users')
  .where('role', 'in', ['admin', 'moderator'])
  .toSQL();
// Result: SELECT * FROM users WHERE role IN ('admin', 'moderator')

Subqueries in Where Clauses

import { raw } from '@hypequery/clickhouse';

// Where with subquery
const query = db
  .table('users')
  .where('id', 'in', raw('(SELECT user_id FROM orders WHERE total > 1000)'))
  .toSQL();
// Result: SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE total > 1000)

Joins with Where Conditions

// Where conditions on joined tables
const query = db
  .table('orders')
  .leftJoin('users', 'orders.user_id', 'users.id')
  .where('orders.status', 'eq', 'completed')
  .where('users.country', 'eq', 'US')
  .toSQL();
// Result: SELECT * FROM orders LEFT JOIN users ON orders.user_id = users.id WHERE orders.status = 'completed' AND users.country = 'US'

Advanced Patterns

Conditional Where Clauses

// Build dynamic where clauses
function buildUserQuery(filters: {
  minAge?: number;
  status?: string;
  country?: string;
}) {
  let query = db.table('users');
  
  if (filters.minAge) {
    query = query.where('age', 'gte', filters.minAge);
  }
  
  if (filters.status) {
    query = query.where('status', 'eq', filters.status);
  }
  
  if (filters.country) {
    query = query.where('country', 'eq', filters.country);
  }
  
  return query;
}

// Usage
const result = buildUserQuery({ minAge: 18, status: 'active' });

OR Conditions

// Multiple OR conditions using whereGroup
const query = db
  .table('users')
  .whereGroup((builder) => {
    builder
      .where('email', 'like', '%@gmail.com')
      .orWhere('email', 'like', '%@yahoo.com')
      .orWhere('email', 'like', '%@hotmail.com');
  })
  .toSQL();
// Result: SELECT * FROM users WHERE (email LIKE '%@gmail.com' OR email LIKE '%@yahoo.com' OR email LIKE '%@hotmail.com')

Type Safety

The where method provides full TypeScript support:

interface UserSchema {
  users: {
    id: 'UInt32';
    name: 'String';
    age: 'UInt8';
    email: 'String';
    status: 'String';
  };
}

const db = createQueryBuilder<UserSchema>();

// ✅ Type-safe column references
const query = db
  .table('users')
  .where('age', 'gte', 18) // TypeScript knows 'age' is a valid column
  .where('status', 'eq', 'active')
  .toSQL();

// ❌ TypeScript error for invalid column
const query2 = db
  .table('users')
  .where('invalid_column', 'eq', 'value') // TypeScript error
  .toSQL();