How to calculate subtraction of 2 Sql Query - mysql

I want to do a subtraction operator between entotalitem and extotalitem.query that I use retrieve data from the same table that is tbl_orders_data.
I have tried by creating 2 queries, the first is the query to retrieve entotalitem and the second query to retrieve extotalitem
$encheck = DB::table('tbl_orders_data')
->select('slot_id', DB::raw('sum(total_item) as entotalitem'))
->where('id_order_data', 'like', 'PBM' . '%')
->groupBy('slot_id')
->pluck('entotalitem');
$excheck = DB::table('tbl_orders_data')
->select('slot_id', DB::raw('sum(total_item) as extotalitem'))
->where('id_order_data', 'like', 'PBK' . '%')
->groupBy('slot_id')
->pluck('extotalitem');
$en = $encheck;
$ex = $excheck;
dd($en - $ex);
Should I only need to use one query? or should I make 2 queries as I have tried?
please help me, thanks

You may use conditional aggregation here:
$check = DB::table('tbl_orders_data')
->select('slot_id', DB::raw("sum(case when id_order_data like 'PBM%' then total_item else 0 end) -
sum(case when id_order_data like 'PBK%' then total_item else 0 end) as totalitem"))
->groupBy('slot_id')
->pluck('totalitem');

Related

Substraction in MYSQL with some condition

I want to do SUM and SUBTRACTION upon certain condition within mysql query
i have try like this,
asuming the $balance= 655.000.000 then total amount inside my_table = IDR 80.000.000 and USD 500.000
$currency_id = 1;
$balance = 655.000.000;
DB::table('my_table as a')
->join('master_currencies as b', 'a.master_currency_id', 'b.id')
->where('a.id', $id)
->selectRaw("SUM(
CASE
WHEN $currency_id = a.master_currency_id THEN $balance - a.amount
ELSE
a.amount
END) AS net_value, b.symbol, b.id as master_currency_id"
)
->groupBy('b.id')
->get();
The code above should give the result
[
{"net_value":"575.000.000","symbol":"IDR","master_currency_id":1},
{"net_value":"500.000","symbol":"USD","master_currency_id":2}
]
but the result i got is
[
{"net_value":"1.885.000.000","symbol":"IDR","master_currency_id":1},
{"net_value":"500.000","symbol":"USD","master_currency_id":2}
]
Note:
Please ignore dots between numbers, in my database i'm not using these dots. it is for inquiry purposes only
If you have more than one row of IDR then it might be a problem with order of operations.
For example say you have to values (100.000.000) and (50.000.000) then for IDR SUM(655.000.000-100.000.000, 655.000.000-50.000.000)=1.160.000.000 and is not the same as 655.000.000-SUM(100.000.000,50.000.000)=505.000.000 the problem being that each row in the group that you aggregate gets a clean $balance.
You could potentially solve this by doing:
$currency_id = 1;
$balance = 655.000.000;
DB::table('my_table as a')
->join('master_currencies as b', 'a.master_currency_id', 'b.id')
->where('a.id', $id)
->selectRaw("
(CASE
WHEN a.id=$currency_id $balance-SUM(a.amount)
ELSE
SUM(a.amount)
END) AS net_value, b.symbol, b.id as master_currency_id")
->groupBy('b.id')
->get();

How to select multiple where conditions using codeigniter?

my table
This is my table i have to display the data using multiple where conditions. First i select using dms_expire_date,for this i got answer and i am using dms_doc_name in where conditions but i didn't got correct result.
I have tired so far.
]
See this picture if i use "or" in "where" i got testie not within this date.but if i use "and" in "where" i didn't got result for dms_expiry_date
See this picture
i don't know how to do this.please help to solve this problem.
SELECT * FROM `dms_document` WHERE dms_expire_date BETWEEN '2020-05-01' AND '2020-07-16' AND dms_doc_name = '' OR dms_category_id = '' OR dms_subcategory_id=''
I have tired in array also but i didn't result.
$this->db->select('*');
$this->db->join('dms_category as C', 'C.dms_category_id = D.dms_category_id', 'left outer');
$this->db->join('dms_sub_category as S', 'S.dms_subcategory_id = D.dms_subcategory_id', 'left outer');
$this->db->where('dms_expire_date >=', $newstart);
$this->db->where('dms_expire_date <=', $newend);
$this->db->where(array('dms_doc_name' =>$docname,'D.dms_category_id'=>$category,'D.dms_subcategory_id'=>$subcategory));
$data['documents']= $this->db->get('dms_document as D')->result_array();
try
SELECT *
FROM dms_document
WHERE dms_expire_date BETWEEN $newstart AND $newend
AND CASE WHEN $docname IS NULL THEN 1 = 1 ELSE dms_doc_name = $docname END
AND CASE WHEN $category IS NULL THEN 1 = 1 ELSE dms_category_id = $category END
AND CASE WHEN $subcategory IS NULL THEN 1 = 1 ELSE dms_subcategory_id = $subcategory END
--
edited. waiting for clearance.
if I get what you mean correctly, it is problem with understanding AND, OR, and the priority with brackets ()
--
if anyone want to use the fiddle, I have created the sample data for this issue
You can write OR using CodeIgniter's or_where() (v3 docs) or orWhere() (v4 docs).
//your initial query
$sql = "SELECT
*
FROM
`dms_document`
WHERE
dms_expire_date BETWEEN '2020-05-01' AND '2020-07-16'
AND dms_doc_name = ''
OR dms_category_id = ''
OR dms_subcategory_id=''";
//building the same query using CI
$this->db->select('*');
$this->db->from('dms_document');
$this->db->where('dms_expire_date >=', '2020-05-01');
$this->db->where('dms_expire_date <=', '2020-07-16');
$this->db->where('dms_doc_name', '');
$this->db->or_where('dms_category_id', '');
$this->db->or_where('dms_subcategory_id', '');
You can confirm the query this generates by running $this->db->_compile_select(); or $this->db->last_query(); (https://stackoverflow.com/a/6145021/1499877 for reference).
echo '<pre>';
var_dump($sql);
var_dump($this->db->_compile_select());
echo '</pre>';
die();

Codeigniter query for selecting sum of multiple columns with where conditions on each row

I have made this function to get sum of population percent based on group_id as 1,2 and 3 but its not working
public function ethnicity($value='')
{
$this->db->select('SUM(population_percent) as p1 where group_id=1,SUM(population_percent) as p2 where group_id=2,SUM(population_percent) as p3 where group_id=3', FALSE);
$this->db->from('ethnic_group');
$data=$this->db->get()->row_array();
return $data;
}
You need to use IF or CASE when need to do sum with this type of condition
Use this query
public function ethnicity($value='')
{
$sql = "SELECT
SUM(CASE WHEN group_id='1' THEN population_percent ELSE 0 END) p1,
SUM(CASE WHEN Type='2' THEN population_percent ELSE 0 END) p2,
SUM(CASE WHEN Type='3' THEN population_percent ELSE 0 END) p3,
FROM ethnic_group LIMIT 1";
$data = $this->db->query($sql)->row_array();
return $data;
}
When you use $this->db->select() you are writing the 'select' part of a query. To write the 'where' you should use $this->db->where('group_id=3').
In case you want to write an entire query and tell CodeIgniter to run it, you can use $this->db->query($sql) with $sql beign the actual query you want to run as seen in the documentation here.
So I think it should look something like this:
$sql = 'your query here';
$data = $this->db->query($sql)->row_array();
return $data;

How to specify an array in the Where clause using Moodle DB API Call?

I want to filter data based on an array, similar to "in" keyword in a query:
SELECT count(*) as number_of_records,
count(CASE WHEN result = 'SUCCESS' THEN 1 END) as successful_builds_no,
min(CASE WHEN result = 'FAILURE' THEN 0 ELSE 1 END) as is_success,
min(duration) as best_duration,
max(build_date) as build_date
FROM mdl_selenium_results
WHERE build_date in ('2014-03-13', '2014-03-12')
GROUP BY build_date
How to achieve that using Moodle DB api??
If you are creating an SQL query to use within Moodle, you could just use the IN keyword, exactly as you have done in the example.
Alternatively, to make it a bit more cross-DB compatible, and to make your queries run a bit faster when there is only one item in the list, you can write:
list($dsql, $dparam) = $DB->get_in_or_equal(array('2014-03-13', '2014-03-12'), SQL_PARAMS_NAMED);
$sql = "SELECT count(*) as number_of_records,
count(CASE WHEN result = 'SUCCESS' THEN 1 END) as successful_builds_no,
min(CASE WHEN result = 'FAILURE' THEN 0 ELSE 1 END) as is_success,
min(duration) as best_duration,
max(build_date) as build_date
FROM {selenium_results}
WHERE build_date $dsql
GROUP BY build_date";
$result = $DB->get_records_sql($sql, $dparams);
OR, if you just want to get all the matching records from the given table (and then worry about doing the calculations in PHP), you could write:
$result = $DB->get_records_list('selenium_results', 'build_date', array('2014-03-13', '2014-03-12'));
(I've not run any of the code above, so apologies for any typos)

Using comparison as alias in select for Doctrine2

Trying to do this in Doctrine2:
...->createQuery('SELECT m.id, (m.status != 1) as verified...
But that throws an error - if I take parenthesis off I get another error. How do I achieve this m.status comparison?
Thanks
Doctrine 2 doesn't support these comparisons in the SELECT clause (at least not up to 2.3, not sure about 2.4).
You can use a CASE expression as workaround:
SELECT m.id, CASE WHEN m.status != 1 THEN 1 ELSE 0 END AS verified ...
or:
SELECT m.id, CASE WHEN m.status = 1 THEN 0 ELSE 1 END AS verified ...
If you need verified for an ORDER BY clause (or something like that), but don't actually need it in the result, you can use the HIDDEN expression:
SELECT m.id, CASE WHEN m.status = 1 THEN 0 ELSE 1 END AS HIDDEN verified ...
A completely different solution is to write a custom DQL function.
You can use the solution proposed here: Cumulative DQL with Doctrine
When working with entities, keep in mind that adding selects will make the query return an array for each result:
$res = $em->createQueryBuilder()
->from('BlogPost', 'p')
->select('p')
->addSelect('(2+3) AS dummy')
->getQuery()->getResult();
Iterating over $res will return an array:
foreach($res as $mixed){
echo get_class($mixed[0]); //$mixed[0] contains the BlogPost
echo $mixed['dummy']; //displays the dummy result (5)
}
check this out: 13.2.4. Using Expr* classes to create conditionals
using Expression methods you could do something like:
$qb = $this->entityManager->createQueryBuilder();
$query = $qb->select('m.id')
->from('Entities\MyEntity', 'm')
/*neq() is the "not equal" comparison function*/
->where($qb->expr()->neq('m.status', $someValue)),
->getQuery();