0

select(), addSelect(), selectRaw() — column selection

Beginner5 min read·lv-13-002
sql

Concept

Column selection controls which columns are included in the SQL SELECT clause. Returning only needed columns reduces data transfer, memory usage, and can leverage covering indexes.

select(string|array ...$columns): Replace the current select with the given columns. Replaces any previous select() call.

addSelect(string|array ...$columns): Add columns to an existing select. Useful when building queries incrementally.

selectRaw(string $expression, array $bindings = []): Include a raw SQL expression in the SELECT list. Bindings are positional PDO placeholders.

DB::raw(string $expression): Create a raw SQL expression. Can be used in any clause. Be careful of SQL injection — only use with trusted values or bound parameters.

Column aliases: 'total_price as total', DB::raw('COUNT(*) as user_count').

Distinct: ->distinct() adds SELECT DISTINCT.

selectSub(Closure|Builder, string $alias): Use a subquery as a selected column.

Important: select() resets the column list. If middleware or a trait adds columns and you call select() later, previous columns are dropped. Use addSelect() to avoid this.

Code Example

php
<?php
use Illuminate\Support\Facades\DB;

// Select specific columns
$users = DB::table('users')
    ->select('id', 'name', 'email', 'created_at')
    ->get();

// Select with alias
$orders = DB::table('orders')
    ->select('id', 'user_id', 'total as order_total', 'status')
    ->get();
// $order->order_total

// addSelect — append without replacing
$query = DB::table('users')->select('id', 'name');
if ($needsEmail) {
    $query->addSelect('email');
}
$users = $query->get();

// selectRaw — raw expression in SELECT
$stats = DB::table('orders')
    ->selectRaw('
        COUNT(*) as total_orders,
        SUM(total) as revenue,
        AVG(total) as avg_order,
        DATE(created_at) as order_date
    ')
    ->groupBy('order_date')
    ->get();

// selectRaw with bindings — prevent injection
$users = DB::table('users')
    ->selectRaw('id, name, DATEDIFF(NOW(), created_at) as days_since_joined')
    ->get();

// DB::raw in select array
$users = DB::table('users')
    ->select(['id', 'name', DB::raw('YEAR(created_at) as join_year')])
    ->get();

// distinct
$roles = DB::table('users')->select('role')->distinct()->pluck('role');
// ['admin', 'user', 'editor']

// Subquery as column — most recent order total for each user
$users = DB::table('users')
    ->select('id', 'name')
    ->selectSub(function($query) {
        $query->from('orders')
              ->selectRaw('MAX(total)')
              ->whereColumn('user_id', 'users.id');
    }, 'latest_order_total')
    ->get();
// $user->latest_order_total — without loading orders