Codeigniter-Problem while using yearweek('datefield') in where class - php

Today I met the problem in CodeIgniter framework when I was trying to filter using date field with yearweek(). Here is my query in normal without CodeIgniter style definition
SELECT b.name as branch,str_to_date(concat(yearweek(gp.createddate), 'sunday'), '%X%V %W') as week,sum(case when amount>0 then qty else 0 end) as purchase_quantity,sum(case when amount>0 then gp.amount else 0 end) as purchase_amount,sum(case when amount<0 then qty else 0 end) as return_quantity,sum(case when amount<0 then gp.amount else 0 end) as return_amount FROM `group_purchase` gp LEFT JOIN `branch` b ON gp.branchid=b.id WHERE yearweek(gp.createddate)=yearweek('2018-12-24') GROUP BY gp.branchid,yearweek(gp.createddate) ORDER BY yearweek(gp.createddate) DESC
That was worked fine and result was produced accurately.i was use yearweek() for grouping data in week wise.when i was implementing this query into codeigniter all the things was worked fine except yearweek().I attached my codeigniter model for above query below
function getPurchasereport($limit,$offset,$order_column,$order_type,$parameters)
{
$this->db->select("b.name as branchname,str_to_date(concat(yearweek(gp.createddate), 'sunday'), '%X%V %W') as week,sum(case when amount>0 then qty else 0 end) as purchase_quantity,sum(case when amount>0 then gp.amount else 0 end) as purchase_amount,sum(case when amount<0 then qty else 0 end) as return_quantity,sum(case when amount<0 then gp.amount else 0 end) as return_amount");
if($parameters['branch']!=NULL){
$this->db->like('gp.branchid',$parameters['branch']);
}
if($parameters['cdatefrom']!=NULL){
$this->db->where('yearweek(gp.createddate)',yearweek("$parameters['cdatefrom'])");
}
$this->db->group_by(array("gp.branchid", "yearweek(gp.createddate)"));
if(empty($order_column) || empty($order_type)){
$this->db->order_by('yearweek(gp.createddate)','asc');
}else{
$this->db->order_by($order_column,$order_type);
}
if($limit!=0){
$this->db->limit($limit,$offset);
}
$this->db->join('branch b','gp.branchid=b.id ','left');
$query = $this->db->get('group_purchase gp');
if($query->num_rows()>0){
return $query->result_array();
}else{
return FALSE;
}
}
it produced error like below
error

The error you have is because of this line
if($parameters['cdatefrom']!=NULL){
$this->db->where('yearweek(gp.createddate)',yearweek("$parameters['cdatefrom'])");
}
the function yearweek is not valid PHP function, therefore you cannot use it that way.
you need to replace it with the below:
if($parameters['cdatefrom']!=NULL){
$this->db->where('yearweek(gp.createddate)',date('YW',strtotime($parameters['cdatefrom'])));
}

Related

PHP/SQL select based on sum result

I'm having a hard time limiting my query results based on sum. Example code:
$rows = Entry::find()
->section('cities')
->select('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
I want to only select states where 0 cities are "covered". Running my code above the "having" line seems to be ignored (it includes both zero and non-zero cases). I tried using "where" instead of "having" but it results in a PDOException - "Invalid use of group function". I assume "having" is the right approach, but that I'm making a novice mistake -- any tips?
/*** UPDATE 1 ***/
Thanks #scaisEdge and #angelm for the tip -- groupBy helps, but it's still not working as expected. It seems the "having" line is still ignored. With modified code:
$test = Entry::find()
->section('cities')
->select(['state', 'covered', "sum(case when covered = '1' then 1 else 0 end) as numCovered"])
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
I log the following results:
{state: "AL", covered: "0", numCovered: "0"}
{state: "AK", covered: "0", numCovered: "0"}
{state: "CA", covered: "1", numCovered: "19"}
{state: "CO", covered: "0", numCovered: "0"}
...
As you can see above, states (CA) are included when numCovered is clearly not 0.
I also tried the following code for "having" (which I assume is the same):
->having("numCovered = 0")
/*** UPDATE 2 ***/
Using a reduced test case suggested by #cpalmer still results in "CA" being selected despite having numCovered = 19. I'm now wondering if this is a peculiarity with Craft CMS, since it would seem my query is correct?
$test = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
Is there a way to write this query without having?
/*** UPDATE 3 ***/
As suggested by the DB Fiddle posted by #pocketrocket my sql should work. Dumping the raw sql suggests the having line is ignored. The issue likely resides with CraftCMS/Yii and my lack of understanding of the environment.
First of all: I am total with #Olivier, you should decouple the SQL part of your question from the architecture itself. For the SQL part, it's important to let others know which database or SQL dialect you use (MySQL, PostgreSQL, MsSQL...).
Just guessing it's MySQL what you are using:
Both ways should actually work, repeating the querypart in having or referencing it by name as suggested by user126587
If both don't work and you would like to work without having maybe you can implement a subselect?
SELECT
state,
sum(case when covered = '1' then 1 else 0 end) as numCovered
FROM cities
GROUP BY state
HAVING sum(case when covered = '1' then 1 else 0 end) = 0;
SELECT
state,
sum(case when covered = '1' then 1 else 0 end) as numCovered
FROM cities
GROUP BY state
HAVING numCovered = 0;
SELECT * FROM (
SELECT
state,
sum(case when covered = '1' then 1 else 0 end) as numCovered
FROM cities
GROUP BY state
) sub_select
WHERE sub_select.numCovered = 0;
You can play around with it here: DB Fiddle Link
try add a groupBy() for state
$rows = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
Try removing 'covered' from your selected columns. In some SQL databases, when you group your data, simply having a column in your select statement that isn't in the group by statement or in an aggregate can cause an error. In your case, I think this column is causing the unexpected results. If you really want to include it, throw it into an aggregate and alias it, like 'MAX(covered) as covered'
$test = Entry::find()
->section('cities')
->select(['state', "sum(case when covered = '1' then 1 else 0 end) as numCovered"])
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = 0")
->asArray()
->all();
Try putting in the having part "numCovered = 0".
Well my guess is you are forgetting a single quote around the 0 in your having clause.
$test = Entry::find()
->section('cities')
->select('state')
->groupBy('state')
->having("sum(case when covered = '1' then 1 else 0 end) = '0'")
->asArray()
->all();

MySQL Advanced multidimensional query with CONCAT, JSON and IF statement

I working on one complex listing from database and decide to do all possible requests via one query.
Here is working example:
"SELECT
`c`.`categories_id`,
`c`.`categories_status`,
IF(`c`.`categories_status` = 1, 'Active', 'Not Active') AS `categories_status_name`,
TRIM(`cd`.`categories_name`) AS `categories_name`,
TRIM(`cd`.`concert_date`) AS `concert_date`,
TRIM(`cd`.`concert_time`) AS `concert_time`,
TRIM((
SELECT
CONCAT(
'{\"total_quantity\":',
SUM(CASE WHEN `p`.`products_quantity` > 0 THEN `p`.`products_quantity` ELSE 0 END),
',\"total_price\":\"',
SUM(`p`.`products_price`),
'\"}'
)
FROM
`products_to_categories` `ptc`,
`products` `p`
WHERE
`ptc`.`section_id` = `cd`.`section_id`
AND
`p`.`products_id` = `ptc`.`products_id`
)) AS `products_available`,
TRIM((
SELECT
CONCAT(
'{\"total_quantity\":',
SUM(CASE WHEN `op`.`products_quantity` > 0 THEN `op`.`products_quantity` ELSE 0 END),
',\"total_price\":\"',
SUM(`op`.`final_price`),
'\"}'
)
FROM
`products_to_categories` `ptc`,
`orders_products` `op`
WHERE
`ptc`.`section_id` = `cd`.`section_id`
AND
`op`.`products_id` = `ptc`.`products_id`
AND
`op`.`orders_products_status` != 1
)) AS `products_sold`,
TRIM((
SELECT
CONCAT(
'{\"total_quantity\":',
SUM(CASE WHEN `op`.`products_quantity` > 0 THEN `op`.`products_quantity` ELSE 0 END),
',\"total_price\":\"',
SUM(`op`.`final_price`),
'\"}'
)
FROM
`products_to_categories` `ptc`,
`orders_products` `op`
WHERE
`ptc`.`section_id` = `cd`.`section_id`
AND
`op`.`products_id` = `ptc`.`products_id`
AND
`op`.`orders_products_status` = 1
)) AS `products_pending`
FROM
`categories` `c`,
`categories_description` `cd`
WHERE
`c`.`categories_id` = `c`.`section_id`
AND
`cd`.`categories_id` = `c`.`categories_id`
GROUP BY `c`.`categories_id`
ORDER BY `c`.`categories_status` DESC;"
This work great but my main problem is how to do check IF/ELSE or CASE WHEN for custom defined new fields: products_available, products_sold and products_pending?
Problem is that if products not exists inside table orders_products I not get my generated JSON and that's made a small conflict inside PHP.
I can do check in PHP but want to avoid that part and just print JSON like:
{"total_quantity":0,"total_price":"0.0000"}
FROM
`products_to_categories` `ptc`,
`orders_products` `op`
*
WHERE `products_id` =
(SELECT COALESCE(`products_id`,0))
*
AND
`ptc`.`section_id` = `cd`.`section_id`

Increment temperory variable value in case statement query

Tring to calculate count according to coloumn value with case statement and I used following code for doing this:
SET #tempVariable1 := 0;
SET #tempVariable2 := 0;
SELECT EMPLOYEEID,count(ADNUMBER),
CASE
WHEN AEERROR <> '--' then #tempVariable1:=#tempVariable1+1
ELSE 0
END AS Ext_err,
CASE
WHEN INTERNALERRORS <> '--' then #tempVariable2:=#tempVariable2+1
ELSE 0
END AS Int_err
FROM employee_productivity_details group by(EMPLOYEEID) LIMIT 2,20;
It works correct when I run on workbench but when I set this query in PHP variable like $sql then it shows error. So how can I set temperory variable with in query? Any other way to do this?
Does this do what you want?
SELECT EMPLOYEEID, count(ADNUMBER),
SUM(AEERROR <> '--') AS Ext_err,
SUM(INTERNALERRORS <> '--' ) AS Int_err
FROM employee_productivity_details
group by(EMPLOYEEID)
LIMIT 2, 20;
This is working fine for me as per need.
SELECT EMPLOYEEID,
count(ADNUMBER),
COALESCE(SUM(CASE INTERNALERRORS WHEN INTERNALERRORS <> '--'
THEN 0 ELSE 1 END), 0) as IntErr,
COALESCE(SUM(CASE AEERROR WHEN AEERROR <> '--'
THEN 0 ELSE 1 END), 0) AS ExtErr
FROM employee_productivity_details
group by(EMPLOYEEID) order by EMPLOYEEID LIMIT 2,20;

Left join MYSQL returns false

I am trying to do a MYSQL LEFT JOIN query, however I'm getting an error:
"Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given in". Because the query which is returned is false.
The code is:
$query = "
SELECT a.page
, SUM(b.views) views
, ROUND(SUM(b.costs)/1.38,2) costs
, ROUND(SUM(a.amount),2) REV
, ROUND(SUM(a.amount) - SUM(b.costs)/1.38,2) PNL
FROM revenues a
LEFT
JOIN costs b
ON a.page = b.page
WHERE a.date BETWEEN '$start_date' AND '$end_date'
AND a.country = '$country'
AND b.date BETWEEN '$start_date' AND '$end_date'
GROUP
BY a.page";
$result = mysqli_query($connection,$query);
if ($result != false) {
$foundnum = mysqli_num_rows($result);
if ($foundnum == 0) {
echo 'No results found.';
}
} else {
echo 'returned false';
}
printQuery($result);
printQuery is a function of me which creates a html table.
If I do two seperate queries on the tables I get correct tables back. My seperate queries are:
$query = "SELECT page, round(sum(amount),2) as REV FROM revenues WHERE date between '$start_date' AND '$end_date' AND country = '$country' GROUP BY page" ;
$query2 = "SELECT page, sum(views) as views, round(sum(costs)/1.38,2) as costs FROM costs WHERE date between '$start_date' AND '$end_date' GROUP BY page";
Can someone please point to me where the mistake is.
Table revenues consists of the columns:
date: date
amount: float (NULL if no revenue was made)
country: varchar
Table costs cosists of the columns:
date: date
costs: float (always >= 0)
views: int
Thanks
The following is usless:
else {
echo 'returned false';
}
Replace it with something like:
else {
echo "Query failed.\nMySQLi error: " . mysqli_error();
}
You get points for at least checking your return values, but you need to make your code fail descriptively at least for dev purposes.

Mysql only outputs last loops data

i am trying to output statistics of calls made by agents across all dialing campaigns called for the day. there are multiple campaigns, currently 3, dialed in a day. I get the campaign data from a table name that changes by campaign like so custom_16546546 and custom_1564654. I run a query to get the numeric part of the column name then pass that as a variable in to another query that outputs the users statistics. This is where it only displays data from what i can tell is the last query loops information. I have displayed the array data from the first query to confirm the table names are being stored and it looks fine.
$today = "2013-05-29";
$customquery = "SELECT distinct( entry_list_id) FROM vicidial_list where entry_list_id > 0 and last_local_call_time between '$today 00:00:00' and '$today 23:59:59';" ;
$customresult = mysql_query($customquery) or die(mysql_error());
$customrows = mysql_num_rows($customresult);
while ($customrowResult = mysql_fetch_array($customresult))
{
$customID[] = $customrowResult["entry_list_id"];
}
$z = 0;
if(!$customID){
//echo " Please Select a valid date range: ".$today. " - ".$today." is not valid" ;
}else{
while($z<$customrows)
{
$query = "SELECT
vicidial_users.user,
vicidial_users.full_name,
vicidial_log.list_id,
COUNT(CASE WHEN (vicidial_log.status = 'SALE') THEN 1 ELSE null END) as sumcountSamnt,
COUNT(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].up_amt <> '') THEN 1 ELSE null END) as sumcountupAmnt,
COUNT(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].cc_num <> '') THEN 1 ELSE null END) as sumccverifiedcountAmnt,
COUNT(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].bank_act <> '') THEN 1 ELSE null END) as sumbankverifiedcountAmnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].cc_num <> '') THEN custom_$customID[$z].s_amount ELSE null END) as sumccverifiedAmnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE' AND custom_$customID[$z].bank_act <> '') THEN custom_$customID[$z].s_amount ELSE null END) as sumbankverifiedAmnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].d_amt ELSE null END) as sumDamnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].up_amt ELSE null END) as sumUpamnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].md_amt ELSE null END) as sumMdamnt,
SUM(CASE WHEN (vicidial_log.status = 'SALE') THEN custom_$customID[$z].s_amount ELSE null END) as sumSamnt
FROM
vicidial_log
INNER JOIN
vicidial_users
ON
(vicidial_log.user = vicidial_users.user)
INNER JOIN
custom_$customID[$z]
ON
(vicidial_log.lead_id = custom_$customID[$z].lead_id)
WHERE
call_date
BETWEEN
'$today 00:00:00'
AND
'$today 23:59:59'
AND
vicidial_log.user != 'VDAD'
AND
vicidial_users.user_group != 'TX-Training'
GROUP BY
vicidial_log.user, vicidial_log.campaign_id
";
//This query is used to sum loop data data
$queryResult = mysql_query($query) or die(mysql_error()); //This line perfomrs query error handling
$z++;
}
here is a snippet of how the data is displayed
$result = mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_assoc($result))
{
echo "<tr>\n";
//--fullname and userID
echo "<td> ".$row["full_name"]. " - ".$row["user"]."</td>\n";
//Agent total sales amount
if ($row["sumcountSamnt"] == '0') {
echo "<td>$nosalestxt</td>\n";
} else {
echo "<td> $".$row["sumSamnt"]."</td>\n";
}
}
So i want to be able to display a sum total of data for each user from all the campaigns they dialed from.
Thanks in advance for your help
EDIT: i use &row from a while loop to output the data and yes Chris i would like to store it an array, but i guess im just missing it, thanks again
Based on the code snippets you have given it looks like you are overwriting the value of $queryResult after each execution of the loop. Perhaps you meant to execute the query and put the results into an array (or something similar) to loop over and display later.
Also I notice you reference $row[] in your output, how are you assigning a value to that variable?

Categories