Manipulating rows from a table - sql

function getData(){
$id = $this->uri->segment(3);
$this->db->select("t.*, mt.mid as mid, mt.amt as mtamt, m.user");
$this->db->from("transaction as t");
$this->db->join("mtrans as mt", "mt.tid = t.id and mt.mid = '$id'", "left outer");
$this->db->join("member as m", "m.id = mt.aid", "left outer");
$query = $this->db->get();
$data = $query->result_array();
return $data;
}
For starters, this is my code. How do I manipulate it so that mt.amt with the same t.id and mt.mid will be displayed as 1 row showing the sum of all mt.amt in the mt.amt column?

Related

TYPO3 9.5 Extbase Query for UidArray

I´ve got the following SQL-Query
$uidArray = explode(",", $uids);
foreach ($uidArray as $uid) {
$dynamicUid[] = '`uid` LIKE \''.$uid.'\'';
}
$query = $this->createQuery();
$query->statement("SELECT * FROM `tx_myextension_domain_model_thi` WHERE ".implode($dynamicUid, " OR "));
return $query->execute();
This works fine but I want to have it like this:
$uidArray = explode(",", $uids);
$query = $this->createQuery();
foreach ($uidArray as $key => $value) {
$constraints[] = $query->equals('uid', $value);
}
return $query->matching(
$query->logicalAnd($constraints)
)->execute();
Here I get the following Output with the Query Parser :
'SELECT `tx_myextension_domain_model_thi`.* FROM `tx_myextension_domain_model_thi`
`tx_myextension_domain_model_thi`
WHERE ((`tx_myextension_domain_model_thi`.`uid` = :dcValue1) AND
(`tx_myextension_domain_model_thi`.`uid` = :dcValue2)) AND
(`tx_myextension_domain_model_thi`.`sys_language_uid` IN (0, -1)) AND
(`tx_myextension_domain_model_thi`.`pid` = 0) AND
((`tx_myextension_domain_model_thi`.`deleted` = 0) AND (
`tx_myextension_domain_model_thi`.`t3ver_state` <= 0) AND
(`tx_myextension_domain_model_thi`.`pid` <> -1) AND
(`tx_myextension_domain_model_thi`.`hidden` = 0) AND
(`tx_myextension_domain_model_thi`.`starttime` <= 1607084460) AND
((`tx_myextension_domain_model_thi`.`endtime` = 0)
OR (`tx_myextension_domain_model_thi`.`endtime` > 1607084460)))'
And the Uids as dcValue-Array.
dcValue1 => '1' (1 chars)
dcValue2 => '2' (1 chars)
Maybe someone can help me to rewrite this, because unfortunately I can't get any further!
Thanks :)
Did you try the in operator?
public function yourFunctionName($uid)
{
$query = $this->createQuery();
$query->in('uid', $uidArray);
return $query->execute();
}
Assuming that your array looks like this:
$uidArray = [
0 = '34',
1 = '15',
3 = '88'
]
EDIT
If you do not care about where your objects are stored then you can do the following.
public function yourFunctionName($uid)
{
$query = $this->createQuery();
$query->getQuerySettings()->setRespectStoragePage(FALSE);
$query->matching(
$query->in('uid', $uidArray)
);
return $query->execute()];
}
Which is going to ignore the pid in the query

How to make a UNION with Doctrine?

I'm trying to do the following query:
public function findByNotifications($ownerId)
{
$em = $this->getEntityManager();
$query = $em->createQuery('
SELECT n FROM
(SELECT n FROM DelivveWebBundle:UserAd n
INNER JOIN n.ad ad
WHERE ad.owner = :ownerId
LIMIT 20
UNION
SELECT n FROM DelivveWebBundle:UserAd n
INNER JOIN n.user u
INNER JOIN n.ad ad
WHERE u.id = :ownerId
AND ad.status = :progress
LIMIT 20)
notofication
LIMIT 20;
')->setParameter('ownerId', $ownerId)
->setParameter('progress', Constant::AD_IN_PROGRESS);
$result = $query->getResult();
return $result;
}
to generate all my notifications:
public function showNotificationsAction()
{
$this->denyAccessUnlessGranted('ROLE_USER', null, 'Unable to access this page!');
$owner = $this->getUser();
$repository = $this->getDoctrine()->getRepository('DelivveWebBundle:UserAd');
$notifications = $repository->findByAdOwner($owner->getId());
return $this->render('DelivveWebBundle:Ad:notification.html.twig', array(
'owner' => $owner,
'notifications' => $notifications
));
}
The idea is to do a search on AdUser table that returns all notifications that have ads that logged User owns, along with any notifications that logged User requested.
Notification the User requested is a line of AdUser table that has the column the user logged in User.
I decided to breaking in two searches and giving a marge in results
public function findByAdOwner($ownerId)
{
$qb = $this->getEntityManager()->createQueryBuilder('n');
return $qb->select('n')
->from('DelivveWebBundle:UserAd', 'n')
->join('n.ad', 'ad')
->where('ad.owner = :ownerId')
->setParameter('ownerId', $ownerId)
->setMaxResults(20)
->getQuery()
->getResult();
}
public function findByUserNotify($userId)
{
$qb = $this->getEntityManager()->createQueryBuilder('n');
return $qb->select('n')
->from('DelivveWebBundle:UserAd', 'n')
->join('n.ad', 'ad')
->where('n.user = :userId')
->andWhere('ad.status = :status')
->setParameter('userId', $userId)
->setParameter('status', Constant::AD_IN_PROGRESS)
->setMaxResults(20)
->getQuery()
->getResult();
}
public function findNotifcations($userId){
$notification = $this->findByAdOwner($userId);
$append = $this->findByUserNotify($userId);
return array_merge($notification, $append);
}
To become more readable'll just put after something that distinguishes the two types of notice to do the treatment on the page.
I discovered that there is a way to add commands to the doctrine that does not exist, but appears to be quite complex if anyone knows do this, put the answer please.

ignore where statement if parameter is null in doctrine

Hi i have a problem in QueryByilder in Doctrine. i wrote a Query that has 2 parameter and they affect in where statement. i want to ignore where statement if the related parameter was null. for example if $play = 3 and $theater = null the query must return all tickets with play 3 and whatever theater
this is my code:
public function getAllSearchedTickets($play,$teater){
return $this->getEntityManager()->createQuery('
select s from mtadminBundle:ReserveLocation s
join s.reserve a
join a.sance b
where a.acceptCode != 0
and b.play = :play
and b.teater = :teater')
->setParameters(array('play'=>$play,'teater'=>$teater))->getResult();
}
thank you.
You should use the QueryBuilder for this, to do it more efficiently, I'll show you how you do yours and then the same with the QueryBuilder as example:
Yours:
public function getAllSearchedTickets($play,$teater){
$query = 'select s from mtadminBundle:ReserveLocation s'.
'join s.reserve a'.
'join a.sance b'.
'where a.acceptCode != 0');
$paramArray = array();
if( $play ) {
$query .= ' and b.play = :play';
$paramArray['play'] = $play;
}
if( $teater ) {
$query .= ' and b.teater = :teater';
$paramArray['teater '] = $teater;
}
return $this->getEntityManager()->createQuery($query)
->setParameters($paramArray)->getResult();
}
QueryBuilder:
public function getAllSearchedTickets($play,$teater){
$queryBuilder = $this->getEntityManager()->createQueryBuilder();
$queryBuilder->select('s')
->from('mtadminBundle:ReserveLocation', 's')
->join('s.reserve', 'a')
->join('a.sance', 'b')
->where('a.acceptCode != 0');
if( $play ) {
$queryBuilder->andWhere('b.play = :play');
$queryBuilder->setParameter('play', $play);
}
if( $teater ) {
$queryBuilder->andWhere('b.teater = :teater');
$queryBuilder->setParameter('teater', $teater);
}
return $queryBuilder->getResult();
}

(prestashop) How can I detect if there's a catalog price rule bound to a category or some of its parents?

I have catalog price rules for some categories. In frontend, in category.tpl, I have to notify if there are special prices bound to that specific category or some of its parents.
For now, I'm building a function on the controller that finds it with a query. I was wandering if there was some shortcut for doing this.
I wrote a function (a CategoryController method) to solve my problem and I share:
public function get_category_promo(){
//get the active country, since promo are also country-based
if($this->context->customer->isLogged()){
$current_country = Customer::getCurrentCountry($this->context->customer->id);
} else {
$current_country = $this->context->country->id;
}
$db = Db::getInstance();
$sql = '
SELECT
truncate(`reduction`,0) as reduction,
`reduction_type`,
`from`,
`to`,
`type` as category_type,
`value` as id_category,
`id_parent` as category_parent,
`level_depth` as depth
FROM
`'._DB_PREFIX_.'specific_price_rule_condition` rule_condition
INNER JOIN
`'._DB_PREFIX_.'specific_price_rule_condition_group` rule_group
on rule_condition.`id_specific_price_rule_condition_group` = rule_group.`id_specific_price_rule_condition_group`
INNER JOIN
`'._DB_PREFIX_.'specific_price_rule` price_rule
on price_rule.`id_specific_price_rule` = rule_group.`id_specific_price_rule`
INNER JOIN
`'._DB_PREFIX_.'category` category
on rule_condition.`value` = category.`id_category`
WHERE rule_condition.`type` = "category"';
$parents = $this->category->getParentsCategories();
array_shift($parents);//first is == this->category so I shift it out
$sql_aux = ' and (rule_condition.`value` = ' . $this->category->id_category;
foreach($parents as $parent){
$sql_aux .= ' or rule_condition.`value` = ' . $parent["id_category"];
}
$sql_aux .= ')';
$sql_aux .= ' and price_rule.`id_country` = ' . $current_country;
$sql_aux .= ' order by level_depth desc';
$sql .= $sql_aux;
$promo_data = $db->executeS($sql);
$promo_data = count($promo_data) > 0 ? $promo_data : null;
if(!$promo_data) return false;//stop
function validate_date($promo){
//if there are no dates
if((int)$promo['to'] == 0 && (int)$promo['from'] == 0) return true;
//if there is end promo date
if((int)$promo['to'] != 0){
$to = new DateTime($promo['to']);
//...and is still valid
if($to >= new DateTime('NOW')) return true;
}
}//end validate
//refine query results
$filtered = array_values(array_filter($promo_data,'validate_date'));
$promo_data = $filtered[0];//if there are more than one promo on the same category, the promo on the higher depth is used form the system, so I need only that promo
//promo without dates. Only refine to/from to better use in smarty
if((int)$promo_data['to'] == 0 && (int)$promo_data['from'] == 0){
$promo_data['to'] = 0;
$promo_data['from'] = 0;
$this->context->smarty->assign('promo_data', $promo_data);
return true;
}
if((int)$promo_data['to'] != 0){//promo ha send date
$to = new DateTime($promo_data['to']);
if($to >= new DateTime('NOW')){
$promo_data['to'] = $to->format('d-m-Y');
} else {
return false;//not a valid date
}
}
if((int)$promo_data['from'] != 0){
$from = new DateTime($promo_data['from']);
$promo_data['from'] = $from->format('d-m-Y');
} else {
$promo_data['from'] = 0;
}
$this->context->smarty->assign('promo_data', $promo_data);
}//end get_category_promo

return the result of a query and the total number of rows in a single function

This is a question as might be focused on working in the best way, if there are other alternatives or is the only way:
Using Codeigniter ... I have the typical 2 functions of list records and show total number of records (using the page as an alternative). The problem is that they are rather large. Sample 2 functions in my model:
count Rows:
function get_all_count()
{
$this->db->select('u.id_user');
$this->db->from('user u');
if($this->session->userdata('detail') != '1')
{
$this->db->join('management m', 'm.id_user = u.id_user', 'inner');
$this->db->where('id_detail', $this->session->userdata('detail'));
if($this->session->userdata('management') === '1')
{
$this->db->or_where('detail', 1);
}
else
{
$this->db->where("id_profile IN (
SELECT
e2.id_profile
FROM profile e, profile e2, profile_path p, profile_path p2
WHERE e.id_profile = " . $this->session->userdata('profile') . "
AND p2.id_profile = e.id_profile
AND p.path LIKE(CONCAT(p2.path,'%'))
AND e2.id_profile = p.id_profile
)", NULL, FALSE);
$this->db->where('MD5(u.id_user) <>', $this->session->userdata('id_user'));
}
}
$this->db->where('u.id_user <>', 1);
$this->db->where('flag <>', 3);
$query = $this->db->get();
return $query->num_rows();
}
results per page
function get_all($limit, $offset, $sort = '')
{
$this->db->select('u.id_user, user, email, flag');
$this->db->from('user u');
if($this->session->userdata('detail') != '1')
{
$this->db->join('management m', 'm.id_user = u.id_user', 'inner');
$this->db->where('id_detail', $this->session->userdata('detail'));
if($this->session->userdata('management') === '1')
{
$this->db->or_where('detail', 1);
}
else
{
$this->db->where("id_profile IN (
SELECT
e2.id_profile
FROM profile e, profile e2, profile_path p, profile_path p2
WHERE e.id_profile = " . $this->session->userdata('profile') . "
AND p2.id_profile = e.id_profile
AND p.path LIKE(CONCAT(p2.path,'%'))
AND e2.id_profile = p.id_profile
)", NULL, FALSE);
$this->db->where('MD5(u.id_user) <>', $this->session->userdata('id_user'));
}
}
$this->db->where('u.id_user <>', 1);
$this->db->where('flag <>', 3);
if($sort) $this->db->order_by($sort);
$this->db->limit($limit, $offset);
$query = $this->db->get();
return $query->result();
}
You see, I repeat the most of the functions, the difference is that only the number of fields and management pages.
I wonder if there is any alternative to get as much results as the query in a single function. I have seen many tutorials, and all create 2 functions: one to count and another to show results ... Will there be more optimal?
you have to use SQL_CALC_FOUND_ROWS in your query, something like this:
SELECT SQL_CALC_FOUND_ROWS first_name, age FROM table
to return the result you can simply create a new array:
$result['total'] = $this->db->query("SELECT FOUND_ROWS() as total")->row_array();
$result['result_array'] = $query->result();
return $result;