Hallo,


Ik ben bezig met een zoek systeem op mijn gebruikers tabel. Nu wil ik graag kunnen zoeken op het ID én op de naam van het permissie pakket. Nu heb ik de volgende query:


        SELECT 
		 user.id,
		 username, 
		 email, 
		 DATE_FORMAT(reg_date, '%d-%m-%Y %k:%i') as reg_date, 
		 permission_pack.name 
		FROM 
		 user
		LEFT JOIN 
		 permission_pack 
		ON (user.permission_pack_id = permission_pack.id)
		WHERE
		 user.id LIKE '%".$this->input->post('id')."%' AND 
		 username LIKE '%".$this->input->post('username')."%'  AND 
		 email LIKE '%".$this->input->post('email')."%' AND 
		 DATE_FORMAT(reg_date, '%d-%m-%Y %k:%i') LIKE '%".$this->input->post('reg_date')."%' AND 
		 permission_pack_id LIKE '%".$this->input->post('permission_pack')."%' OR 
		 permission_pack.name LIKE '%".$this->input->post('permission_pack')."%'
		LIMIT ".$limit_min.",".$limit_max


Nu moeten de laatste twee expressies van de WHERE clause in één zitten waardoor ik het ID maar ook de naam van het pakket kan vinden. Hoe kan ik dit doen?

Nick.
Waarschijnlijk heb je een OR in plaats van een AND operator nodig. Als je AND gebruikt betekent het dat 1 record zowel moet matchen op naam, als op id. Als je de matches wilt hebben op naam of id heb je OR nodig. Let dan ook op het operator precedence, een AND operater gaat namelijk boven een OR operator, wat betekent dat deze twee statement niet hetzelfde resultaat zullen opleveren:

WHERE id=1 OR naam='bla' AND email='iets'

WHERE (id=1 OR naam='bla') AND email='iets'


Daarnaast, als id een integer is (wat je meestal gebruikt voor een id), dan is een LIKE clause niet echt verstandig. Zo krijg je namelijk ook alle ids die er op lijken, zoek is dus op id=1, dan krijg ik niet alleen het record met id=1, maar alle records waar een 1 in het id zit (en dat is dus ongeveer 10% van alle records. Lijkt mij niet dat je dat wilt. Bedenk ook dat LIKE clauses erg traag zijn, omdat ze (met een wildcard aan het begin) geen gebruik meer kunnen maken van een index en in het geval van een int veld ook nog eens een cast moeten uitvoeren.
Bedankt voor je antwoord!

Ik heb het nu werkende gekregen. Het zal nog niet het meest efficient zijn maargoed.


$search[] = (!empty($this->input->post('id')) ? "user.id = '".$this->input->post('id')."'" : '');
		$search[] = (!empty($this->input->post('username')) ? "username LIKE '%".$this->input->post('username')."%'" : '');
		$search[] = (!empty($this->input->post('email')) ? "email LIKE '%".$this->input->post('email')."%'" : '');
		$search[] = (!empty($this->input->post('reg_date')) ? "DATE_FORMAT(reg_date, '%d-%m-%Y %k:%i') LIKE '%".$this->input->post('reg_date')."%'" : '');
		$search[] = (!empty($this->input->post('permission_pack')) ? "(permission_pack_id = '".$this->input->post('permission_pack')."' OR permission_pack.name LIKE '%".$this->input->post('permission_pack')."%')" : '');
		
		$where = "";
		
		for($i=0; $i < count($search); $i++)
		{
			if(!empty($search[$i]))
			{
				if(!empty($where))
				{
					$where .= " AND " . $search[$i];
				}
				else
				{
					$where = " WHERE " . $search[$i];
				}
			}
		}
		
		$query =
		"SELECT 
		 user.id,
		 username, 
		 email, 
		 DATE_FORMAT(reg_date, '%d-%m-%Y %k:%i') as reg_date, 
		 permission_pack.name 
		FROM 
		 user
		LEFT JOIN 
		 permission_pack 
		ON (user.permission_pack_id = permission_pack.id)
		 ".$where." 
		LIMIT ".$limit_min.",".$limit_max;
		return $this->db->query($query)->result();


EDIT Heb de for loop iets aangepast.
Als je die search array iets anders opbouwt kan je die where clause veel makkelijker doen:

<?php
if ( !empty($this->input->post('id') ) $search[] = "user.id = '".$this->input->post('id')."'";
//en de andere net zo

if ( count( $search ) > 0 ){
  $where = 'WHERE '.implode( ' AND ', $search ); 
}  
?>

Reageren