Multiple between statements in sql builder - sql

I am creating a fairly large query using laravel 4 sql builder. it roughly looks like, get data from table
where(yada yada)and where age between(yada, yada)or between(yada, yada) and where(yad yada).
But what I want is this.
where(yada yada)and where (age between(yada, yada)or between(yada, yada)) and where(yad yada).
some code:
$query = Subject::grabBasic();// start writing query, which results to grab.
$agelength = sizeof($fromAgeValue);
$count = 0;
$ageflag = 0;
foreach( array_combine($fromAgeValue, $toAgeValue) as $from=>$to ){
$count+=1;
if($ageflag==0){
if(($from!=null)&&($to!=null)){
$query = Subject::addfromAgeToAge($query, $from, $to);
$ageflag=1;
}
}else if(($from!=null)&&($to!=null)){
$query = Subject::orfromAgeToAge($query, $from, $to);
}
}
... keep adding to $query
Subject code:
static function addfromAgeToAge($query, $fromAge, $toAge){
return $query->whereBetween('Age', array($fromAge, $toAge));
}
static function orfromAgeToAge($query, $fromAge, $toAge){
return $query->orWhereBetween('Age', array($fromAge, $toAge));
}
So, is there a way to write the addToAge builder function to take in the arrays of fromage and toage values and create a statement, which when added to the rest of the query, will give the desired results. e-g. the sql query will have parentheses in the correct place.
I would also like to do this without raw queries, I suspect there is a way to do this I just haven't been able to find it.
Thanks,

I buckled and used raw queries :(
Here's what it looks like.
$agecounter = 0;// tells me how many from age to age pairs were filed out coorrectly.
foreach( array_combine($fromAgeValue, $toAgeValue) as $from=>$to ){
if(($from!=null)&&($to!=null)){
$agecounter+=1;
}
}
$agelength = sizeof($fromAgeValue);
$ageflag = 0;
foreach( array_combine($fromAgeValue, $toAgeValue) as $from=>$to ){
if($ageflag==0){
if(($from!=null)&&($to!=null)){
$query = Subject::addfromAgeToAge($query, $from, $to, $agecounter); // ages put in for loop when multiple are added.
$ageflag=1; // add or's
$agecounter -=1;
}
}else if(($from!=null)&&($to!=null)){
$query = Subject::orfromAgeToAge($query, $from, $to, $agecounter);
$agecounter -=1;
}
}
and in my Model:
static function addfromAgeToAge($query, $from, $to, $count){
if($count>1){
return $query->whereRaw('( Age between ? and ?', array($from, $to));
}
return $query-> whereBetween('Age', array($from, $to));
}
static function orfromAgeToAge($query, $from, $to, $count){
if($count==1){
return $query->orWhereRaw(' Age between ? and ?)', array($from, $to));
}
return $query->orWhereRaw(' Age between ? and ?', array($from, $to));//('Age', array($fromAge, $toAge));
}
Hope this helps someone else put ()'s in a query builder.

Related

Phalcon: specific column on joined PHQL

The below PHQL generates a complex resultset like it should:
$phql = "SELECT User.*, ProductUser.* "
. "FROM ProductUser "
. "INNER JOIN User "
. "WHERE ProductUser.product_id = 5";
Replacing ProductUser.* with an existing column like ProductUser.id causes an error:
MESSAGE: The index does not exist in the row
FILE: phalcon/mvc/model/row.zep
LINE: 67
This is version 2.0.6. Is this a bug or am I making a mistake somewhere? According to the documentation it should be fine.
It was my mistake (expecting the row to always be an object).
I hope this helps someone because looping complex resultsets is not in the documentation.
$result = $this->modelsManager->createQuery($phql)->execute();
if ($result instanceof \Phalcon\Mvc\Model\Resultset\Complex) {
foreach ($result as $rows) {
foreach ($rows as $row) {
if (is_object($row)) {
$modelData = $row->toArray());
// this is what I needed
} else {
$id = $row;
}
}
}
}
First of all you're missing the ON clause in your query.
Anyways, it's easier and more error prone to use Phalcon's query builder for querying:
<?php
// modelManager is avaiable in the default DI
$queryBuilder = $this->modelsManager->createBuilder();
$queryBuilder->from(["product" => 'Path\To\ProductUser']);
// Inner join params are: the model class path, the condition for the 'ON' clause, and optionally an alias for the table
$queryBuilder->innerJoin('Path\To\User', "product.user_id = user.id", "user");
$queryBuilder->columns([
"product.*",
"user.*"
]);
$queryBuilder->where("product.id = 5");
// You can use this line to debug what was generated
// $generatedQuery = $queryBuilder->getPhql();
// var_dump($generatedQuery);
// Finish the query building
$query = $queryBuilder->getQuery();
// Execute it and get the results
$result = $query->execute();
// Now use var_dump to see how the result was fetched
var_dump($result);
exit;

Yii - loop an array from findAll

I'm trying to implement for loop to update time.
$files = File::model()->findAll('type="A" AND id='.$id);
function files($files,$limit=null){
$limit = isset($limit) ? $limit : count($files);
for($i=0;$i<=$limit;$i++){
$files[$i]->date = date('Y:m:d H:i:s');
$files[$i]->update();
}
}
This function return error undefined offset 1.
What is the result of findAll method? Is it a multidimensional array of records? And How could I fixed this error?
You are setting $limit to count($files) but using $i<=$limit in your loop. Should be < instead.
for($i=0; $i<$limit; $i++){
Since there is a chance of an external $limit being applied you could use a foreach loop with a conditional break.
foreach($files as $a => $file) {
if($a == $limit) {
break;
}
$file->date = date('Y:m:d H:i:s');
$file->update();
}
Note that findAll() without a limit retrieves all the records from the databases for that table. Perhaps you should consider adding the limit through CDbCriteria

Empty response when making a Select with 2 where clauses

My function of XMLRPC works like this, check if content already exists at my website, if it is up-to-date and update it if necessary.
To do it I check for it´s number ( both content types can have same number) it´s hash (unique) and type.
Before I had only one kind of content, and my function was working properly , but now I need to check also content type instead of only number and hash.
that is the problem, whem I try to do it, I got an empty anwser. My Function now is like this:
$query = db_query("SELECT (table_num.field_num) FROM (table_num, table_type) WHERE table_num.entity = table_type.entity AND table_num.field_num = :num AND table_type.field_type = :type", array(':num' => $num, ':type' =>$type));
foreach ($query as $record) {
if($record->rowCount()==0) return 0;
else {
$query = db_query("SELECT (table_hash.field_hash) FROM (table_hash, table_type) WHERE table_hash.entity = table_type.entity AND table_hash.field_hash = :hash AND table_type.field_type = :type", array(':hash' => $hash, ':type' =>$type));
foreach ($query as $record) {
if($record->rowCount()==1) return 1;
else{
$query = db_query("SELECT (table_num.entity_id) FROM (table_num, table_type) WHERE table_num.entity = table_type.entity AND table_num.field_num = :num AND table_type.field_type = :type", array(':num' => $num, ':type' =>$type));
foreach ($query as $record) {
echo $record->field_entity_id;
}
return $record;
P.S. when it returns 0 it does not exists in my DB, 1 is when it´s up to date and entity when I need to update it.
Sorry for long SQL but I just start to use it, and I didn´t manage to get it shorter.
Does someone have any idea why I am getting an empty anwser?
The way your building your queries is dangerous and lead to SQL injection as your not escaping your variables.
Instead of:
$query = db_query("SELECT (table_num.field_num) FROM table_num WHERE table_num.field_num = $num AND table_type.field_type = $type");
You can use:
$query = db_query("SELECT (table_num.field_num) FROM table_num WHERE table_num.field_num = :num AND table_type.field_type = :type", array(':num' => $num, ':type' =>$type));
This way Drupal will sanitize your variables before inserting them so you know it won't lead to any vulnerabilities.
I don't actually fully understand what your question is asking - if you could clarify it a bit I'll see if I can help with that too...

my query take a long time to run ,why?

I have a query that returns c.a 1800 records( not many) but It takes long time to ran (10 seconds) but I can not understand why?
this is my query that takes a long time:
SELECT tb_KonzeptFunktionen.Konzept AS KonzeptID, tb_KonzeptFunktionen.Funktion,
tb_KonzeptFunktionen.Version,
qryFunktionen_Übersicht.ID,
qryFunktionen_Übersicht.Fehlerpfad_Kommentar AS Kommentar,
qryFunktionen_Übersicht.Fehlerpfadname,
qryFunktionen_Übersicht.Fehlerpfad_CDT,
qryFunktionen_Übersicht.Fehlerpfad_Kommentar,
qryFunktionen_Übersicht.symptombasiert,
qryFunktionen_Übersicht.Beschreibung_vorhanden,
qryFunktionen_Übersicht.Max_Pfad,
qryFunktionen_Übersicht.Max_Info,
qryFunktionen_Übersicht.Max_Status,
qryFunktionen_Übersicht.Max_Strategie,
qryFunktionen_Übersicht.Max_Prüfplan,
qryFunktionen_Übersicht.Min_Pfad,
qryFunktionen_Übersicht.Min_Info,
qryFunktionen_Übersicht.Min_Status,
qryFunktionen_Übersicht.Min_Strategie,
qryFunktionen_Übersicht.Min_Prüfplan,
qryFunktionen_Übersicht.Sig_Pfad,
qryFunktionen_Übersicht.Sig_Info,
qryFunktionen_Übersicht.Sig_Status,
qryFunktionen_Übersicht.Sig_Strategie,
qryFunktionen_Übersicht.Sig_Prüfplan,
qryFunktionen_Übersicht.Plaus_Pfad,
qryFunktionen_Übersicht.Plaus_Info,
qryFunktionen_Übersicht.Plaus_Status,
qryFunktionen_Übersicht.Plaus_Strategie,
qryFunktionen_Übersicht.Plaus_Prüfplan,
qryFunktionen_Übersicht.Beschreibung_allgemein,
qryFunktionen_Übersicht.Funktionsname
FROM tb_KonzeptFunktionen RIGHT JOIN qryFunktionen_Übersicht
ON tb_KonzeptFunktionen.Funktion = qryFunktionen_Übersicht.Funktionsname
WHERE (((tb_KonzeptFunktionen.Konzept)=[Formulare]![frm_Fahrzeug]![ID]))
and this is another related query to above query:
SELECT tbFunktionen_Übersicht.*,
tbFunktionen.Funktionsname,
tbFunktionen.Funktionsbeschreibung,
tbFunktionen.diagnoserelevant,
tbFunktionen.ID AS FunktionsID
FROM tbFunktionen_Übersicht INNER JOIN tbFunktionen
ON tbFunktionen_Übersicht.Funktion = tbFunktionen.ID
ORDER BY tbFunktionen.Funktionsname, tbFunktionen_Übersicht.Fehlerpfadname;
I added an index to the fields that appear in ORDER oder JOINS but no effect
Would you please help me if possible?
Please refer to this post,hier you can find the answer
for me PDO brought improvement in my sql query's: http://www.php.net/manual/en/intro.pdo.php
//SQL-HANDLING*******************************************************//
//*********************************************************************//
//General Example-----------------
//$sqlHandling = new sqlHandling;
//$sqlHandling->connectSQL($sqlArray['host'], $sqlArray['user'],$sqlArray['pass'], $sqlArray['dbName']);
//$tableNameArray = $sqlHandling->showTablesSQL($sqlHandling->dbh);
class sqlHandling{
//PDO - Object/ callItOutside with: $sqlClass->dbh
public $dbh = null;
//connectDataBase-------------------//
//-----------------
//example: $dbh = connectSQL('localhost','admin','1admin','test');
//start transaction
//$dbh->beginTransaction();
//-----------------
//end transaction
//$dbh->commit();
//$dbh = null;
//-----------------
//1:SQL-Location
function connectSQL($host, $user, $pass, $dbname){
//endPrevTransaction
if($this->dbh != null){
$this->dbh->commit();
$this->dbh = null;
}
//establish connection
try{
$this->dbh = new PDO('mysql:host='.$host.';dbname='.$dbname, $user, $pass);
$this->dbh->exec('SET CHARACTER SET utf8');
return $this->dbh;
}catch(PDOException $e){
print 'Error!: ' . $e->getMessage() . '<br/>';
die();
return FALSE;
}
}
//createColumnSQL-------------------//
//example: createColumnSQL($dbh, 'backupexample', array('SomeName1 VARCHAR(30)', 'SomeName2 VARCHAR(30)', 'SomeName3 VARCHAR(30)', 'SomeName4 VARCHAR(30)'));
//1:PDO connection/2:table/3:array holding columns
function createColumnSQL($dbh, $table, $columns){
//cicle through each array
foreach($columns as $tempColumn){
//set query
$query = 'ALTER TABLE `'.$table.'` ADD COLUMN '.$tempColumn;
//send the query
$stmt = $dbh->prepare($query);
//send the data
$stmt->execute();
}
}
}
This is only a working example for my PDO sqlHandling Class. I know retrieveAllValues won't help you further but you may adopt this code for your use.
MFG

Best way to get Count for paging in ravenDB

I need to find the number of documents that are in the raven database , so that I can properly page the documents out. I had the following implementation -
public int Getcount<T>()
{
IQueryable<T> queryable = from p in _session.Query<T>().Customize(x =>x.WaitForNonStaleResultsAsOfLastWrite())
select p;
return queryable.Count();
}
But if the count is too large then it times out.
I tried the method suggested in FAQs -
public int GetCount<T>()
{
//IQueryable<T> queryable = from p in _session.Query<T>().Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
// select p;
//return queryable.Count();
RavenQueryStatistics stats;
var results = _session.Query<T>()
.Statistics(out stats);
return stats.TotalResults;
}
This always returns 0.
What am I doing wrong?
stats.TotalResults is 0 because the query was never executed. Try this instead:
var results = _session
.Query<T>()
.Statistics(out stats)
.Take(0)
.ToArray();
The strange syntax to get the statistics tripped me up as well. I can see why the query needs to be run in order to populate the statistic object but the syntax is a bit verbose imo.
I have written the following extension method for use in my unit tests. It helps keep the code terse.
Extension Method
public static int QuickCount<T>(this IRavenQueryable<T> results)
{
RavenQueryStatistics stats;
results.Statistics(out stats).Take(0).ToArray();
return stats.TotalResults;
}
Unit Test
...
db.Query<T>().QuickCount().ShouldBeGreaterThan(128);
...