Drupal - Query to count all nodes of content_type "A" in which field_b is "X" - sql

I need to make a query for a drupal site. Initially I just needed to COUNT the number of nodes for a content type:
$query = "SELECT COUNT(*) amount FROM {node} n WHERE n.type ='A'";
$result = db_query($query)->fetch();
return $result->amount;
Now I need that but only for nodes that have the field_b equal to 'X'. How can I do this?
I tried EntityFieldQuery without sucess:
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
->entityCondition('bundle', 'A')
->fieldCondition('field_b', 'value', 'X');
$results = $query->execute();
return $results->amount;
Any help?

You can set the query to be a count query only by using :
$count = $query->count()->execute();

Related

Query giving double result instead of single

I have two tables: products and current_product_attribute_values
I have tried a join query to filter them as per attribute selected by the user but when I try this with an additional condition it gives me 2 results instead of one it is including the first one which is not matching as per query:
select * from `products` inner join `current_product_attribute_values` on `products`.`id` = `current_product_attribute_values`.`product_id` where `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `product_name` LIKE ?
here is my laravel Controller code :
$all = Input::all();
$q = Input::get('search_text');
$att_val = Input::get('attribute_value');
$subcat = Input::get('subcat_id');
$subcat_name = DB::table('subcategories')->where('id', $subcat)->value('subcategory_name');
$brandname = DB::table('brands')->where('subcat_id', $subcat)->value('brand_name');
$brand_id = DB::table('brands')->where('subcat_id', $subcat)->value('id');
$product_count = DB::table('products')->where('brand_id', $brand_id)->count();
if ($q != "") {
// getting multiple same name params
$query = DB::table('products');
$query->join('current_product_attribute_values', 'products.id', '=', 'current_product_attribute_values.product_id');
$j = 0;
foreach ($all as $key => $values) {
//echo 'my current get key is : ' . urldecode($key). '<br>';
if ($key == $name[$j]) {
$query->where('current_product_attribute_values.attribute_id', '=', $att_id_value[$j]);
echo'<br>';
print_r($query->toSql());
echo'<br>';
//echo '<br> key matched and have some value : <br>';
//echo count($values);
if (count($values) >= 1) {
//echo '<br> it has array inside <br>';
foreach ($values as $val) {
// or waali query in same attribute
echo'<br>';
$query->orwhere('current_product_attribute_values.attribute_value_id', '=', $val);
print_r($query->toSql());
echo'<br>';
}
}
$j++;
}
}
$records = $query->toSql();
$query->where('product_name', 'LIKE', '%' . $q . '%');
$records = $query->toSql();
print_r($records);
$products = $query->paginate(10)->setPath('');
$pagination = $products->appends(array(
'q' => Input::get('q')
));
if (count($products) > 0) {
$filters = DB::table('product_attributes')->where('subcategory_id', $subcat)->get(['attribute_title']);
} else {
$filters = array();
}
$categories = categories::where('add_to_menu', 1)->with('subcategories')->with('brands')->get();
$categoryhome = categories::where('add_to_menu', 1)->with('subcategories')->get();
return view('searchfilter')
->with('productsdata', $products)
->with('filtersdata', $filters)
->with('categories', $categories)
->with('categorieshome', $categoryhome)
->with('subcat_name', $subcat_name)
->with('subcat_id', $subcat)
->with('brandname', $brandname)
->with('product_count', $product_count)
->with('querytext', $q);
}
return 'No Details found. Try to search again !';
its easier if you use raw sql as calling db select function. ex:
$query=DB::select("select * from `products` inner join `current_product_attribute_values` on `products`.`id` = `current_product_attribute_values`.`product_id` where `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `product_name` LIKE ?
");
indeed you can concat vars in raw sql if you need to, ex:
$queryBrands = "select id from brands where subcat_id =".$subcat;
//echo $queryBrands
$queryBrands = DB::select($queryBrands);
By looking at your tables, product table with id value 17 has two records in table current_product_attribute_values in column product_id (I assume this column is used as foreign key to product table).
With select *, you select all of the columns from both tables. So it would most likely cause your query to return multiple records.
My suggestions:
Only select the columns you need. Avoid using select * in the long run, i.e. select product.id, product.description, current_product_attribute_values.attribute_values ......
Make use of GROUP BY
Hope these helps.

Laravel/SQL: return rows where column Equals NOT 'something" and NULL

LARAVEL 5.4 (but probably it's a more general SQL question)
Hello! I have a table with a structure:
Suppose it's my model 'Table'.
I want a query which:
uses (receives) variables :
$id of array ['id', 'string', integer]
where string is '<' or '>'
$status_not_bad = bool;
(if true - include all rows where 'status' !== 'bad' AND 'status' IS NULL);
for example, we are given:
$id = ['id', '>', 0];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id > 0" returns rows 1 and 3.
but if we given:
$id = ['id', '<', 3];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id < 3" returns row 1
(it should be same query which return those results using those variables).
I've never used laravel before so my syntax could be off, but I know you want to use MySQL's ifNull function for this:
Table::where([['id', '>', 0], ['number', '>', 2])->whereRaw("IfNull(status, 'blah') <> 'bad'")->get();
Just chain your ->where() clauses. Maybe also consider wrapping them to prevent conflicting with any additional:
$results = Table::where("id", ">" 0)
->orWhere("number", ">", 2)
->orWhereNull("status")
->get();
Or, wrapped:
$results = Table::where(function($query){
$query->where("id", ">" 0)
->orWhere("number", ">", 2)
->orWhereNull("status");
})->get();
If you want to see what the actual query you're executing is, replace ->get() with ->toSql(), and use dd($result);:
$results = Table::where(...)->toSql();
dd($results);
Edit: Sounds like we need multiple wrapping queries, due to multiple conditions:
$results = Table::where(function($query){
$query->where("status", "!=", "bad")
->where("id", "<", 3); -- "status is not bad and id < 3"
})->orWhere(function($query){
$query->where("status", "!=", "bad")
->where("id", ">", 0); -- "status is not bad and id > 0"
})->get();
That should handle paired conditions as noted in your comment.

TYPO3 Extbase Join

I'm try to make this query with extbase work:
SELECT a.*
FROM tx_apartments_domain_model_apartment a
LEFT
JOIN tx_apartments_domain_model_booking b
ON b.apartment = a.uid
AND b.start <= '2018-07-23'
AND b.end >= '2018-07-21'
WHERE b.uid IS NULL AND a.hidden=0 AND a.deleted=0;
the following code does not work, i get an empty result:
/** #var QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_apartments_domain_model_apartment');
$statement = $queryBuilder
->select('a.*')
->from('tx_apartments_domain_model_apartment','a')
->leftJoin(
'a',
'tx_apartments_domain_model_booking',
'b',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('b.apartment','a.uid'),
$queryBuilder->expr()->lte('b.start', '2018-07-23'),
$queryBuilder->expr()->gte('b.end', '2018-07-21')
)
)
->where(
$queryBuilder->expr()->isNull('b.uid')
)
->execute();
//DebuggerUtility::var_dump($queryBuilder->getSQL());
return $statement->fetchAll();
can anybody help me?
What kind of records do you expect to get?
as uid is a mandantory field you never have records where the uid is NULL.
If you want to access new records which are not stored to the database yet: they get a faked uid like NEW123
This works for me:
/** #var QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('tx_apartments_domain_model_apartment');
$queryBuilder
->getRestrictions()
->removeAll();
$statement = $queryBuilder
->select('a.*')
->from('tx_apartments_domain_model_apartment','a')
->leftJoin(
'a',
'tx_apartments_domain_model_booking',
'b',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('b.apartment','a.uid'),
$queryBuilder->expr()->lte('b.start', $queryBuilder->createNamedParameter('2018-07-23')),
$queryBuilder->expr()->gte('b.end', $queryBuilder->createNamedParameter('2018-07-21'))
)
)
->where(
$queryBuilder->expr()->andX(
$queryBuilder->expr()->isNull('b.uid'),
$queryBuilder->expr()->eq('a.hidden',0),
$queryBuilder->expr()->eq('a.deleted',0)
)
)
->execute();
$results = $statement->fetchAll();
// DebuggerUtility::var_dump($queryBuilder->getSQL());
// DebuggerUtility::var_dump($results);
return $results;
I do not know where exactly you are using this code. Typically I would think that retrieving records from the database should happen in a repository.
If you are using this in the ApartmentRepository and if there is a relation properly configured between apartments and bookings (1:n, I would assume) in the TCA, then you could use something like this:
public function findInDateRange ($dateConstraint)
{
$query = $this->createQuery();
$constraints = [];
$constraints[] = $query->lessThanOrEqual(
'bookings.start',
$dateConstraint['start']
);
$constraints[] = $query->greaterThanOrEqual(
'bookings.end',
$dateConstraint['end']
);
$query->matching($query->logicalAnd($constraints));
return $query->execute();
}
I deliberately left out the b.uid IS NULL part here, as that should always return nothing since uid should be AUTO_INCREMENT. Unless the default query settings are changed, there is also no need to check the disable fields (hidden, deleted) manually.
Note that in order for this to work, the Apartment Domain Model needs a field bookings with a corresponding column in the database (that is something I stumbled over last year).
As a side-note: Is it intentional that you allow for the end to be before the start in your query (start: 2018-07-23, end: 2018-07-21), or is that just exemplary?

Count function in sql query issue

Please, i have this query here:
$query_pag_num = "SELECT COUNT(*) AS count FROM forma";
$result_pag_num = odbc_exec($connection, $query_pag_num) or die(odbc_error());
$row = odbc_fetch_array($result_pag_num);
$count = $row['id'];
The issue is i get this error here:
Undefined index: id where it's: `$count = $row['id'];`
Help please! It won't work without this piece of code here.
I'm using odbc_connect..
Thanks in advance..
your select function will only return 1 column: "count". you are trying to get to column "id"
here is your fixed code
$query_pag_num = "SELECT COUNT(*) AS count FROM forma";
$result_pag_num = odbc_exec($connection, $query_pag_num) or die(odbc_error());
$row = odbc_fetch_array($result_pag_num);
$count = $row['count'];
you do not have any field in your SELECT called 'id'. Try: $count = $row['count'];

How to get particular column in zend using Left join

I am new to zend framework,
Following is the plain mysql query which takes particular column from table,
SELECT jobs_users.id,jobs_users.first_name from jobs_users left join friends on jobs_users.id=friends.friend_id where friends.member_id=29
I tried with zend to implement the above query like below,
public function getFriendsProfileList($id){
$db = Zend_Db_Table::getDefaultAdapter();
$select = $db->select();
$select->from('jobs_users')
->joinLeft(
'friends',
'jobs_users.id=friends.friend_id',
array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo')
)
->where("friends.member_id = ?", $id);
$result = $db->fetchAll($select);
return $result;
}
Here i got result with all column name , not with exact column name which i have given in query.
Kindly help me on this.
Use this instead:
$select->from('jobs_users', array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo'))
->joinLeft('friends', 'jobs_users.id=friends.friend_id')
->where("friends.member_id = ?", '20');
You may also try this:
$select = $db->select();
$select->setIntegrityCheck(false);
$select->joinLeft('jobs_users','',array('jobs_users.id','jobs_users.first_name','jobs_users.last_name','jobs_users.photo'));
$select->joinLeft('friends','jobs_users.id=friends.friend_id', array());
$select->where("friends.member_id = ?", $id);
$result = $db->fetchAll($select);
return $result;