Learn how to join multiple tables with PDOdb.
Join two tables on a matching condition:
$results = $db->find()
->from('users AS u')
->select([
'u.id',
'u.name',
'o.order_id',
'o.total'
])
->join('orders AS o', 'o.user_id = u.id')
->get();
// SQL: SELECT u.id, u.name, o.order_id, o.total
// FROM users u INNER JOIN orders o ON o.user_id = u.idInclude all rows from the left table:
$results = $db->find()
->from('users AS u')
->select([
'u.id',
'u.name',
'o.total' => 'SUM(o.amount)'
])
->leftJoin('orders AS o', 'o.user_id = u.id')
->groupBy('u.id', 'u.name')
->get();Include all rows from the right table:
$results = $db->find()
->from('users AS u')
->select([
'u.id',
'u.name',
'o.order_id'
])
->rightJoin('orders AS o', 'o.user_id = u.id')
->get();$results = $db->find()
->from('users AS u')
->select([
'u.name',
'p.title',
'c.content'
])
->join('posts AS p', 'p.user_id = u.id')
->leftJoin('comments AS c', 'c.post_id = p.id')
->get();$results = $db->find()
->from('orders AS o')
->select([
'o.order_id',
'u.name',
'p.product_name',
'oi.quantity',
'oi.price'
])
->join('users AS u', 'u.id = o.user_id')
->join('order_items AS oi', 'oi.order_id = o.id')
->leftJoin('products AS p', 'p.id = oi.product_id')
->where('o.status', 'completed')
->get();$results = $db->find()
->from('users AS u')
->select(['u.name', 'o.order_id', 'o.total'])
->join('orders AS o', 'o.user_id = u.id')
->where('u.active', 1)
->andWhere('o.status', 'completed')
->andWhere('o.total', 100, '>')
->get();$results = $db->find()
->from('authors AS a')
->select([
'a.name',
'b.title',
'c.name' => 'category_name'
])
->join('books AS b', 'b.author_id = a.id')
->join('categories AS c', 'c.id = b.category_id')
->where('a.country', 'USA')
->orderBy('b.title', 'ASC')
->get();$results = $db->find()
->from('users AS u')
->select(['u.id', 'u.name', 'p.title'])
->leftJoin('posts AS p', 'p.user_id = u.id')
->get();$results = $db->find()
->from('users AS u')
->select([
'user_name' => 'u.name',
'user_email' => 'u.email',
'order_count' => 'COUNT(o.id)'
])
->leftJoin('orders AS o', 'o.user_id = u.id')
->groupBy('u.id', 'u.name', 'u.email')
->get();$results = $db->find()
->from('users AS u')
->select([
'u.id',
'u.name',
'total_orders' => 'COUNT(o.id)',
'total_amount' => 'SUM(o.total)'
])
->leftJoin('orders AS o', 'o.user_id = u.id')
->groupBy('u.id', 'u.name')
->having('COUNT(o.id)', 0, '>')
->get();$results = $db->find()
->from('products AS p')
->select([
'p.name',
'avg_rating' => 'AVG(r.rating)',
'review_count' => 'COUNT(r.id)'
])
->leftJoin('reviews AS r', 'r.product_id = p.id')
->groupBy('p.id', 'p.name')
->having('COUNT(r.id)', 10, '>=')
->orderBy('avg_rating', 'DESC')
->get();$results = $db->find()
->from('public.users AS u')
->select(['u.id', 'a.user_id'])
->leftJoin('archive.users AS a', 'a.user_id = u.id')
->where('u.active', 1)
->get();
// SQL: SELECT u.id, a.user_id FROM public.users u
// LEFT JOIN archive.users a ON a.user_id = u.id// ✅ Faster - only matching rows
$results = $db->find()
->from('users AS u')
->select(['u.name', 'o.total'])
->join('orders AS o', 'o.user_id = u.id')
->get();
// ❌ Slower - all users including those without orders
$results = $db->find()
->from('users AS u')
->select(['u.name', 'o.total'])
->leftJoin('orders AS o', 'o.user_id = u.id')
->get();-- Create index for faster JOINs
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_posts_user_id ON posts(user_id);// ✅ Good: 2-3 JOINs maximum
$results = $db->find()
->from('users AS u')
->join('orders AS o', 'o.user_id = u.id')
->leftJoin('products AS p', 'p.id = o.product_id')
->get();
// ❌ Bad: 5+ JOINs are slow
// Consider denormalizing data or using separate queries$results = $db->find()
->from('users AS u')
->select([
'u.name',
'o.recent_order' => 'MAX(o.created_at)',
'o.total_spent' => 'SUM(o.total)'
])
->join('orders AS o', 'o.user_id = u.id')
->where('o.created_at', '2023-01-01', '>=')
->groupBy('u.id', 'u.name')
->having('SUM(o.total)', 1000, '>')
->orderBy('o.total_spent', 'DESC')
->limit(10)
->get();$results = $db->find()
->from('products AS p')
->select([
'p.name',
'c.category_name',
'total_sold' => 'SUM(oi.quantity)',
'revenue' => 'SUM(oi.quantity * oi.price)'
])
->join('categories AS c', 'c.id = p.category_id')
->join('order_items AS oi', 'oi.product_id = p.id')
->join('orders AS o', 'o.id = oi.order_id')
->where('o.status', 'completed')
->groupBy('p.id', 'p.name', 'c.category_name')
->orderBy('revenue', 'DESC')
->get();- SELECT Operations - SELECT queries
- Aggregations - GROUP BY, HAVING
- Filtering Conditions - WHERE clauses