I have used MySQL interval in my query. In raw type query its working fine but in PHP style, there was some wrong data also returned. I have found the problem that was coming due to the interval in where. I was tried a lot but it can't solve.
Number 1 is my raw query(working fine),
Number 2 is my CodeIgniter code,
Number 3 is my actual query for CodeIgniter code,
NO:1 SELECT str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') as week, `b`.`name` as `branchname`, `g`.`name` as `groupname`, `s`.`streetName`, DATE(s.creationdate) as start_date, DATE(s.maturity_date) as maturity_date, (DATE(s.maturity_date) + INTERVAL 4 WEEK) as nippu_date, `customerName`, `s`.`balance` FROM `super_sales` `s` LEFT JOIN `branch` `b` ON `s`.`branchID`=`b`.`id` LEFT JOIN `group` `g` ON `s`.`groupID`=`g`.`id` LEFT JOIN `super_customer` `c` ON `c`.`customerid`=`s`.`customerid` WHERE DATE(c.lastAttendance) > (DATE(s.maturity_date) + INTERVAL 4 WEEK) AND `c`.`balance` <>0 ORDER BY `week` DESC LIMIT 50
NO 2: $this->db->select("str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') as week,b.name as branchname,g.name as groupname,s.streetName,DATE(s.creationdate) as start_date,DATE(s.maturity_date) as maturity_date,(DATE(s.maturity_date) + INTERVAL 4 WEEK) as nippu_date,customerName,s.balance");
if($parameters['branch']!=NULL){
$this->db->like('s.branchID',$parameters['branch']);
}
// $dat = array('e_date' => ;
// $dat=DATE_ADD(DATE(s.maturity_date) + INTERVAL 4 DAY);
$this->db->where('DATE(c.lastAttendance) >','(DATE(s.maturity_date) + INTERVAL 4 WEEK)');
$this->db->where('c.balance <>',0);
if($parameters['cdatefrom']!=NULL){
$this->db->where('yearweek(s.creationdate)',date('YW',strtotime($parameters['cdatefrom'])));
}
// $this->db->group_by(array("s.branchID", "str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W')"));
if(empty($order_column) || empty($order_type)){
$this->db->order_by('yearweek(s.creationdate)','asc');
}else{
$this->db->order_by($order_column,$order_type);
}
if($limit!=0){
$this->db->limit($limit,$offset);
}
$this->db->join('branch b','s.branchID=b.id ','left');
$this->db->join('group g','s.groupID=g.id ','left');
$this->db->join('super_customer c','c.customerid=s.customerid ','left');
$query = $this->db->get('super_sales s');
echo $this->db->last_query();
if($query->num_rows()>0){
return $query->result_array();
}else{
return FALSE;
}
NO:3 SELECT str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') as week, `b`.`name` as `branchname`, `g`.`name` as `groupname`, `s`.`streetName`, DATE(s.creationdate) as start_date, DATE(s.maturity_date) as maturity_date, (DATE(s.maturity_date) + INTERVAL 4 WEEK) as nippu_date, `customerName`, `s`.`balance` FROM `super_sales` `s` LEFT JOIN `branch` `b` ON `s`.`branchID`=`b`.`id` LEFT JOIN `group` `g` ON `s`.`groupID`=`g`.`id` LEFT JOIN `super_customer` `c` ON `c`.`customerid`=`s`.`customerid` WHERE DATE(c.lastAttendance) > '(DATE(s.maturity_date) + INTERVAL 4 WEEK)' AND `c`.`balance` <>0 ORDER BY `week` DESC LIMIT 50
I have found a problem with comparing 2 queries if I removed upper single quotes covered by (DATE(s.maturity_date) + INTERVAL 4 WEEK) its working fine but I don't know how?
Related
I have to use yearweek() in my CodeIgniter query to group the data by week starting from Tuesday.that was working fine without a problem. then the main problem is to filter was doesn't work with Tuesday dates.that was filtered only yearweek() in where on Sunday dates.
I tried that by writing a raw query that was working fine. then I was analyzing on my query then I have found the problem. that was doesn't show equal(=) symbol between where column and values.i was put my CodeIgniter code and correct raw query then current CodeIgniter equivalent query below
function getbranchSalesreportshift($limit,$offset,$order_column,$order_type,$parameters)
{
$this->db->select("str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') as week,b.name as branchname,g.name as groupname,st.name as shiftname,count(*) as total_sales_party,sum(s.price) as total_sales,count(case when salesAdvanceAmount > 0 then s.customerid end) as total_advance_party,sum(case when salesAdvanceAmount > 0 then salesAdvanceAmount end) as total_advance_amount,count(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) then 1 end ) as old_sales_party,sum(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) THEN s.price END ) as old_sales_amount,count(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN 1 END ) as new_sales_party,sum(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN s.price END ) as new_sales_amount,count(returnID) as return_product,sum(orn.price) as return_amount ");
if($parameters['shift']!=NULL){
$this->db->like('s.shiftID',$parameters['shift']);
}
if($parameters['cdatefrom']!=NULL){
// $this->db->where('yearweek(s.creationdate)',date('YW',strtotime($parameters['cdatefrom'])));
$this->db->where('str_to_date(concat(yearweek(s.creationdate), "tuesday"), "%X%V %W")',date('YW',strtotime($parameters['cdatefrom'])));
}
$this->db->group_by(array("s.shiftID", "str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W')"));
if(empty($order_column) || empty($order_type)){
$this->db->order_by('yearweek(s.creationdate)','asc');
}else{
$this->db->order_by($order_column,$order_type);
}
if($limit!=0){
$this->db->limit($limit,$offset);
}
$uid=$this->session->userdata('id');
$this->db->where('b.ownerid',$uid);
$this->db->join('open_returns orn','s.branchID=orn.branchID ','left');
$this->db->join('shifts st','s.shiftID=st.id ','left');
$this->db->join('group g','s.groupID=g.id ','left');
$this->db->join('branch b','s.branchID=b.id ','left');
$query = $this->db->get('super_sales s');
if($query->num_rows()>0){
return $query->result_array();
}else{
return FALSE;
}
}
this is my equivelent raw query (equal symbol cann't put between column and value near where)
SELECT str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') as week, `b`.`name` as `branchname`, `g`.`name` as `groupname`, `st`.`name` as `shiftname`, count(*) as total_sales_party, sum(s.price) as total_sales, count(case when salesAdvanceAmount > 0 then s.customerid end) as total_advance_party, sum(case when salesAdvanceAmount > 0 then salesAdvanceAmount end) as total_advance_amount, count(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) then 1 end ) as old_sales_party, sum(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) THEN s.price END ) as old_sales_amount, count(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN 1 END ) as new_sales_party, sum(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN s.price END ) as new_sales_amount, count(returnID) as return_product, sum(orn.price) as return_amount FROM `super_sales` `s` LEFT JOIN `open_returns` `orn` ON `s`.`branchID`=`orn`.`branchID` LEFT JOIN `shifts` `st` ON `s`.`shiftID`=`st`.`id` LEFT JOIN `group` `g` ON `s`.`groupID`=`g`.`id` LEFT JOIN `branch` `b` ON `s`.`branchID`=`b`.`id` WHERE str_to_time(concat(yearweek(s.creationdate), "tuesday"), "%X%V %W") '201842' AND `b`.`ownerid` = '189' GROUP BY `s`.`shiftID`, str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') ORDER BY `week` DESC LIMIT 50
I was found correct raw query as below but I need correct CodeIgniter coding for respective filter/where
SELECT str_to_date(concat(yearweek(creationdate), 'sunday'), '%X%V %W') as week,b.name as branchname,g.name as groupname,st.name,count(*) as total_sales_party,sum(price) as total_sales,count(case when salesAdvanceAmount > 0 then customerid end) as total_advance_party,sum(case when salesAdvanceAmount > 0 then salesAdvanceAmount end) as total_advance_amount,count(CASE WHEN DATE(creationdate) <> Date(customerCreationDate) then 1 end ) as old_sales_party,sum(CASE WHEN DATE(creationdate) <> Date(customerCreationDate) THEN price END ) as old_sales_amount,count(CASE WHEN DATE(creationdate) = Date(customerCreationDate) THEN 1 END ) as new_sales_party,sum(CASE WHEN DATE(creationdate) = Date(customerCreationDate) THEN price END ) as new_sales_amount FROM `super_sales` `s` LEFT JOIN branch b ON `s`.branchID=b.id LEFT JOIN `group` g ON `s`.groupID=g.id LEFT JOIN shifts st ON s.shiftID=st.id where str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') = '2018-10-16' AND b.ownerid=189 GROUP BY str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W'),s.shiftID ORDER BY week DESC
I need to filter the data by Tuesday weekdays like week column in select
this is a pretty tough one - because, you've to know how the query builder and the underlying DB Driver are working.
The problem is, usually the Querybuilder suffixes in case of a where condition the given key with an = per default. However in your case it doesn't because it thinks it has an operator.
This exactly happens in the following lines:
https://github.com/bcit-ci/CodeIgniter/blob/develop/system/database/DB_query_builder.php#L681
and
https://github.com/bcit-ci/CodeIgniter/blob/develop/system/database/DB_driver.php#L1485
you may found a bug here - and the best thing is to report it on the Forum.
Your solution for now is to suffix it by your own:
$this->db->where('str_to_date(concat(yearweek(s.creationdate), "tuesday"), "%X%V %W") =',date('YW',strtotime($parameters['cdatefrom'])));
I need to select all dates (day & month) within the next 45 days (regardless of year). The below query has stopped working. Like literally started returning no rows when there is definitely data there.
Is there another way to do this query? Happy to check records within a php loop if needed.
Essentially I need to show all records within the next 45 days, even if the year has lapsed.
SELECT
p.*,
c.company
FROM
products p
LEFT JOIN
customers c
ON c.id = p.id
WHERE
DATE_FORMAT(p.service_date, '%m-%d') >= DATE_FORMAT(CURDATE(), '%m-%d')
AND DATE_FORMAT(p.service_date, '%m-%d') <= DATE_FORMAT((CURDATE() + INTERVAL 45 DAY), '%m-%d')
AND c.email_service = 1
ORDER BY
p.service_date ASC
Worked this out with php
// Get the dates m-d for the next 45 days
for ($i = 0; $i <= 45; $i++) {
$days = '+' . $i . ' days';
$date = date('m-d', strtotime($days));
if ($i != 45) {
$DateQuery .= "'$date',";
} else {
$DateQuery .= "'$date'";
}
}
and Inserted the dates I needed directly into the query
SELECT
p.*,
c.company
FROM
products p
LEFT JOIN
customers c
ON c.id = p.id
WHERE
DATE_FORMAT(p.service_date, '%m-%d') IN
(
$DateQuery
)
AND c.email_service = 1
ORDER BY
p.service_date ASC
I don't know why your original query was utilizing Date_Format() on a column (service_date), already stored in MySQL Date type, for range comparisons. It is not able to use any indexing (if defined) either.
You simply need to add/subtract Interval to the date:
SELECT
p.*,
c.company
FROM
products p
LEFT JOIN
customers c
ON c.id = p.id
WHERE
p.service_date >= CURDATE()
AND p.service_date <= (CURDATE() + INTERVAL 45 DAY)
AND c.email_service = 1
ORDER BY
p.service_date ASC
The best way to solve this problem is to use DAYOFYEAR. The difficult part is dealing with the case when you are within 45 days of the end of the year, in which case you have to split the check to see if the date is between now and the end of the year or the beginning of the year and now + 45 days; otherwise you just check if the day of the year is between now and now + 45 days. Try replacing your condition with this:
CASE WHEN DAYOFYEAR('2018-12-31')-DAYOFYEAR(NOW()) < 45 THEN
DAYOFYEAR(p.service_date) BETWEEN DAYOFYEAR(NOW()) AND DAYOFYEAR('2018-12-31') OR
DAYOFYEAR(p.service_date) BETWEEN 1 AND DAYOFYEAR(NOW() + INTERVAL 45 DAY)
ELSE
DAYOFYEAR(p.service_date) BETWEEN DAYOFYEAR(NOW()) AND DAYOFYEAR(NOW() + INTERVAL 45 DAY)
END
Your full query should then look like this:
SELECT
p.*,
c.company
FROM
products p
LEFT JOIN
customers c
ON c.id = p.id
WHERE
(CASE WHEN DAYOFYEAR('2018-12-31')-DAYOFYEAR(NOW()) < 45 THEN
DAYOFYEAR(p.service_date) BETWEEN DAYOFYEAR(NOW()) AND DAYOFYEAR('2018-12-31') OR
DAYOFYEAR(p.service_date) BETWEEN 1 AND DAYOFYEAR(NOW() + INTERVAL 45 DAY)
ELSE
DAYOFYEAR(p.service_date) BETWEEN DAYOFYEAR(NOW()) AND DAYOFYEAR(NOW() + INTERVAL 45 DAY)
END)
AND c.email_service = 1
ORDER BY
p.service_date ASC
If you are worried about leap years, you could change the DAYOFYEAR('2018-12-31') to DAYOFYEAR(CONCAT(YEAR(NOW), '-12-31'))
I am retrieving today's data from db,I want to retrieve this month,this year data as well,Is it possible in single query? or should I go with separate query for each items?
My query given below,
select sum(it.rate * it.quantity)as sales from invoices i
join invoice_items it on i.id = it.invoice_id
where i.invoice_date > DATE_SUB(NOW(), INTERVAL 1 DAY)
Use conditional aggregation:
select sum(case when i.invoice_date > DATE_SUB(NOW(), INTERVAL 1 DAY) then it.rate * it.quantity
end) as sales_1day,
sum(case when i.invoice_date > DATE_SUB(NOW(), INTERVAL 7 DAY) then it.rate * it.quantity
end) as sales_7day,
sum(case when i.invoice_date > DATE_SUB(NOW(), INTERVAL 1 MONTH) then it.rate * it.quantity
end) as sales_1month,
sum(case when i.invoice_date > DATE_SUB(NOW(), INTERVAL 1 YEAR) then it.rate * it.quantity
end) as sales_1year
from invoices i join
invoice_items it
on i.id = it.invoice_id
I have this query that indexes my images and orders them by popularity but I cant make the user to choose the interval cause there's something wrong with the query:
switch($Data['data']){
case 'daily':$QueryDate='=CURDATE()';break;
case 'weekly':$QueryDate=' BETWEEN SUBDATE(CURDATE(), INTERVAL 7 DAYS) AND NOW()';break;
case 'monthly':$QueryDate='>CURDATE() - INTERVAL 31 DAYS';break;
default: Core::redirect('image/browse/daily/1');break;
}
$IMGDB = new Database('images');
$query = "SELECT *, (derived.`likes` * 2 + derived.`views`) as `popularity` from
(SELECT *,
(SELECT COUNT(*) FROM `likes` WHERE `like`=I.id AND `date`".$QueryDate.") AS `likes`,
(SELECT SUM(`views`) FROM `views` WHERE `id`=I.id AND `date`".$QueryDate.") AS `views`
FROM images AS I
) AS derived
where 1 ORDER BY `popularity` DESC ";
Only the daily case works.
Here is the error:
SQL Error (1064): You have an error in your SQL syntax;..... to use near 'DAYS) AND NOW()) AS likes, (SELECT SUM(views) FROM views WHERE id= I.id A
The correct syntax for specifying an interval of days uses the DAY keyword. You've used DAYS in:
BETWEEN SUBDATE(CURDATE(), INTERVAL 7 DAYS) AND NOW()
and:
> CURDATE() - INTERVAL 31 DAYS
This query returns all of the selected values from today's date to 90 days ago:
SELECT max(cases_visits.created_dt), users_profiles.account_num,
concat(cases.patient_first_initial,
cases.patient_middle_initial, cases.patient_last_initial) AS initials,
concat(users.first_name, ' ',users.last_name) as name
FROM cases
JOIN users_profiles
ON users_profiles.user_id=cases.doctor_id
JOIN cases_visits
ON cases.id=cases_visits.case_id
join users on users.id = cases.doctor_id
WHERE cases_visits.patient_visit_type = 'NP' && cases_visits.created_dt BETWEEN curdate() - INTERVAL 90 DAY AND SYSDATE()
group by users.first_name
I'd like to find a query that will now select the exact same thing, but only if records DO not exist in the previous query. EXAMPLE: return records from > 90 days ago, that do not have records in the past 90 days.
I have tried to do this: (note, 2013-07-03 in the query was 90 days from the first time i ran)
SELECT cases_visits.created_dt, users_profiles.account_num,
concat(cases.patient_first_initial,
cases.patient_middle_initial, cases.patient_last_initial) AS initials,
concat(users.first_name, ' ',users.last_name) as name
FROM cases
JOIN users_profiles
ON users_profiles.user_id=cases.doctor_id
JOIN cases_visits
ON cases.id=cases_visits.case_id
join users on users.id = cases.doctor_id
WHERE cases_visits.created_dt < '2013-07-03'
group by users.first_name
This does not give me the proper data, I think because i need to somehow exclude records that exist from the past 90 days.
THIS IS WHAT IM TRYING TO DO: Select a records with a a value = to 'NP' for the past 90 days, then i need to select records where there is not a np value for greater than 90 days, but these records should be completely unique from the first query (i.e the individual could have a case from within the 90 days, and one 180 days ago, i would not need his records.)
EDIT: I forgot to mention I have tried this query with an error near 'in':
SELECT cases_visits.created_dt, users_profiles.account_num,
concat(cases.patient_first_initial,
cases.patient_middle_initial, cases.patient_last_initial) AS initials,
concat(users.first_name, ' ',users.last_name) as name
FROM cases
JOIN users_profiles
ON users_profiles.user_id=cases.doctor_id
JOIN cases_visits
ON cases.id=cases_visits.case_id
join users on users.id = cases.doctor_id
WHERE cases_visits.created_dt < '2013-07-03'
and cases_visits.patient_visit_type = 'NP'
and not in (select created_dt from cases_visits where cases_visits.patient_visit_type = 'NP' && cases_visits.created_dt BETWEEN curdate() - INTERVAL 90 DAY AND SYSDATE())
group by users.first_name
You could use a subquery:
select * from table where ID NOT IN (select id from table where a=1);
This would essentially select the records from the table that don't match the records the inner query did match.
SELECT * FROM table WHERE cases_visits.created_dt < '2013-07-03'
AND case_visist.SOME_UNIQUE_ID NOT IN
(SELECT case_visist.SOME_UNIQUE_ID FROM table WHERE cases_visits.patient_visit_type = 'NP' && cases_visits.created_dt BETWEEN curdate() - INTERVAL 90 DAY AND SYSDATE() )
You can use NOT IN statement and enter a SELECT statement that select all the records that should be excluded. A some more info in this thread
This set should be visits for the same doctor, same cases but a different visit?
SELECT max(cases_visits.created_dt), users_profiles.account_num,
concat(cases.patient_first_initial,
cases.patient_middle_initial, cases.patient_last_initial) AS initials,
concat(users.first_name, ' ',users.last_name) as name
FROM cases
JOIN users_profiles
ON users_profiles.user_id=cases.doctor_id
JOIN cases_visits
ON cases.id=cases_visits.case_id
JOIN users
ON users.id = cases.doctor_id
WHERE cases_visits.patient_visit_type = 'NP' && cases_visits.created_dt <= curdate() - INTERVAL 90 DAY
AND EXISTS(SELECT *
FROM case_visits AS inside
WHERE inside.case_id = cases.id
AND inside.patient_visit_type = 'NP'
AND inside.created_dt BETWEEN curdate() - INTERVAL 90 DAY AND SYSDATE())
GROUP BY account_num, initials, name