The scenario is I am the admin and I have a session to make, the session table consists of a session_id, coach_name, date(format Y-m-d).
Now I want to count the total activity of the coach every "MONTH".
So my point is how will I get this kind of output in a SQL query.
The desired output is the amount of activity per month, per coach.
Name | No. of session this month
Coach_name1 = 13
Coach_name2 = 5
This is my current query that gives me the coach name but I don't know how to get for each MONTH
public function getAll(){
$query = $this->db->query('SELECT DISTINCT coach_name FROM sessions);
return $query->result();
}
Use this query to get the result.
Use mysql MONTH() to get Month number from date and group by it. You will get all month wise data.
SELECT coach_name,
Count(*) AS activities
FROM sessions
WHERE Month(date) = 8 //for specfic month
GROUP BY coach_name, Month(date) // for all months
Use this query to dynamincally get current month based on system date
SELECT coach_name,
Count(*) AS activities
FROM sessions
WHERE Month(date) = MONTH(CURRENT_DATE()) //for selecting current month.
GROUP BY coach_name
You have to prepare query like below:
select
coach_name,
month(your_date_field),
count(1)
from
your_table
where
month(your_date_field) = 8
group by
coach_name, month(your_date_field)
Which would return records like below,
| coach_name | month(your_date_field) | count(1) |
+---------------+------------------------+------------+
| Coach_name1 | 8 | x |
| Coach_name2 | 8 | x |
| Coach_name3 | 8 | x |
+---------------+------------------------+------------+
In codeigniter
$this->db->select("coach_name, month(your_date_field) as month_number,count(1) as counts");
$this->db->where('month(your_date_field)',8);
$this->db->group_by('coach_name,MONTH(your_date_field)');
$query = $this->db->get('your_table');
// results
foreach ($query->result_array() as $row)
{
// do this to see array
print_r($row);
// to access individual fields
echo $row['coach_name'];
echo $row['month_number'];
echo $row['counts'];
}
Use MySQL's MONTH() in your query. So basically if all your data is in your sessions table try the following in your query.
SELECT DISTINCT(`name`),COUNT(`name`) AS `activity` FROM `session`
WHERE MONTH(`date`)=8 GROUP BY `name`;
Check in SQLFiddle
Related
I have a MySQL table which contains the following type of information:
Date product
2011-12-12 azd
2011-12-12 yxm
2011-12-10 sdx
2011-12-10 ssdd
Here is an example of a script I use to get data from this table:
<?php
$con = mysql_connect("localhost","username","password");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("db", $con);
$sql=mysql_query("SELECT * FROM buy ORDER BY Date");
while($row = mysql_fetch_array($sql))
{
echo "<li><a href='http://www.website/". $row['Date'].".html'>buy ". date("j, M Y", strtotime($row["Date"]))."</a></li>";
}
mysql_close($con);
?>
This script displays every date from the table, e.g.
12.dec 2011
12.dec.2011
10.dec.2011
10.dec.2011
I would like to only display unique dates, e.g.
12.dec.2011
10.dec.2011
Use the DISTINCT operator in MySQL:
SELECT DISTINCT(Date) AS Date FROM buy ORDER BY Date DESC;
use
SELECT DISTINCT Date FROM buy ORDER BY Date
so MySQL removes duplicates
BTW: using explicit column names in SELECT uses less resources in PHP when you're getting a large result from MySQL
Use this query to get values
SELECT * FROM `buy` group by date order by date DESC
The rest are almost correct, except they should order by Date DESC
SELECT DISTINCT(Date) AS Date FROM buy ORDER BY Date DESC;
DISTINCT is always a right choice to get unique values. Also you can do it alternatively without using it. That's GROUP BY. Which has simply add at the end of the query and followed by the column name.
SELECT * FROM buy GROUP BY date,description
Another DISTINCT answer, but with multiple values:
SELECT DISTINCT `field1`, `field2`, `field3` FROM `some_table` WHERE `some_field` > 5000 ORDER BY `some_field`
Use something like this in case you also want to output products details per date as JSON and the MySQL version does not support JSON functions.
SELECT `date`,
CONCAT('{',GROUP_CONCAT('{\"id\": \"',`product_id`,'\",\"name\": \"',`product_name`,'\"}'),'}') as `productsJSON`
FROM `buy` group by `date`
order by `date` DESC
product_id product_name date
| 1 | azd | 2011-12-12 |
| 2 | xyz | 2011-12-12 |
| 3 | ase | 2011-12-11 |
| 4 | azwed | 2011-12-11 |
| 5 | wed | 2011-12-10 |
| 6 | cvg | 2011-12-10 |
| 7 | cvig | 2011-12-09 |
RESULT
date productsJSON
2011-12-12T00:00:00Z {{"id": "1","name": "azd"},{"id": "2","name": "xyz"}}
2011-12-11T00:00:00Z {{"id": "3","name": "ase"},{"id": "4","name": "azwed"}}
2011-12-10T00:00:00Z {{"id": "5","name": "wed"},{"id": "6","name": "cvg"}}
2011-12-09T00:00:00Z {{"id": "7","name": "cvig"}}
Try it out in SQL Fiddle
If you are using a MySQL version that supports JSON functions then the above query could be re-written:
SELECT `date`,JSON_OBJECTAGG(CONCAT('product-',`product_id`),JSON_OBJECT('id', `product_id`, 'name', `product_name`)) as `productsJSON`
FROM `buy` group by `date`
order by `date` DESC;
Try both in DB Fiddle
Depends on what you need.
In this case I suggest:
SELECT DISTINCT(Date) AS Date FROM buy ORDER BY Date DESC;
because there are few fields and the execution time of DISTINCT is lower than the execution of GROUP BY.
In other cases, for example where there are many fields, I prefer:
SELECT * FROM buy GROUP BY date ORDER BY date DESC;
There is a specific keyword for the achieving the same.
SELECT DISTINCT( Date ) AS Date
FROM buy
ORDER BY Date DESC;
I need to get multiple rows with a date_added closest to but not past a user supplied date, grouped by user_id.
I've looked at a bunch of max in group type answers but I'm not quite there:
Get nearest records to specific date grouped by type
SQL Query to show nearest date?
Find closest datetime to specified datetime in mysql query
Get closest date from MySQL table
https://dev.mysql.com/doc/refman/5.0/en/example-maximum-column-group-row.html
This is close: https://stackoverflow.com/a/17038667/5319244. Finds the max date though, I need the max specified by user input, not max outright.
Here's a subset of the data with the correct organisation_id, framework_id and level_id already filtered.
+----+---------+-----------------+--------------+----------+---------------------+
| id | user_id | organisation_id | framework_id | level_id | date_added |
+----+---------+-----------------+--------------+----------+---------------------+
| 2 | 1 | 2 | 1 | 1 | 2015-07-31 14:02:49 |
| 9 | 2 | 2 | 1 | 1 | 2015-09-01 11:05:09 |
| 11 | 1 | 2 | 1 | 1 | 2015-09-07 14:13:39 |
+----+---------+-----------------+--------------+----------+---------------------+
If the supplied date is 2015-09-07. I'd expect to see id's: 9 and 11.
If the supplied date is 2015-09-01. I'd expect to see id's: 2 and 9.
If the supplied date is 2015-07-31. I'd expect to see id: 2.
This query is as close as I got:
SELECT t1.id
, t1.user_id
, t1.date_added
FROM
completed_frameworks AS t1
WHERE date_added = (
SELECT
MAX(date_added)
FROM
completed_frameworks
WHERE
user_id = t1.user_id
AND
date_added <= '2015-09-07 23:59:59'
)
AND
(
t1.organisation_id = 2
AND
t1.framework_id = 1
AND
t1.level_id = 1
)
It returns what I expect for the date: 2015-09-07
When the date is 2015-09-01 however it only returns id 9. Not also 2 as I'd expect.
When the date is 2015-07-31 it returns 0 rows..
Let me know if I there's anything else I can provide.
Cheers!
EDIT:
Thanks for the replies thus far. I need to clarify two points:
1) I don't have a limit. I'm expecting those rows due to the user id's. There could be n users returned. I just want a row for each user where the date_added is closest to the user supplied date.
2) The date supplied will not have a time value. It will be from a simple datepicker UI. In my example query I've added the time of 23:59:59 to encompass all of that day.
Try this subquery instead. The organisation_id/framework_id/level_id filter is moved into the subquery and it now returns the right values for the examples you've given.
SELECT t1.id, t1.user_id, t1.date_added
FROM
completed_frameworks AS t1
WHERE date_added = (
SELECT
MAX(date_added)
FROM
completed_frameworks
WHERE
user_id = t1.user_id
AND
date_added <= '2015-09-01 23:59:59'
AND
organisation_id = 2
AND
framework_id = 1
AND
level_id = 1
)
Here is a sample query you could use for an input date of '2015-09-07 14:13:39'. The inner query returns the input date along with the next highest date. This temporary table is then used to filter completed_frameworks to give you only records from the two dates most recent to the input date.
SELECT t1.id, t1.user_id, t1.date_added
FROM completed_frameworks t1
INNER JOIN
(
SELECT cf.date_added
FROM completed_frameworks cf
GROUP BY cf.date_added
HAVING cf.date_added <= '2015-09-07 14:13:39'
ORDER BY cf.date_added DESC
LIMIT 2
) t2
ON t1.date_added = t2.date_added
WHERE t1.organisation_id = 2 AND t1.framework_id = 1 AND t1.level_id = 1
I think this does what you want:
SELECT f.id, f.user_id f.date_added
FROM completed_frameworks f
WHERE date(f.date_added) <= '2025-09-07' -- or whatever your date is
ORDER BY f.date_added DESC
LIMIT 2;
EDIT:
If you want one date per user id that is closest to the specified date, I would suggest:
select f.*
from completed_frameworks f join
(select user_id, max(date_added) as maxda
from completed_frameworks
where date(date_added) <= '2015-09-07'
group by user_id
) u
on f.user_id = u.user_id and f.date_added = maxda
I have three table Like this:
members_tbl
id | Fullname | Email | MobileNo
attendance_in_tbl
id | member_id | DateTimeIN
attendance_out_tbl
id | member_id | DateTime_OUT
I want to select all members for date: 2014-03-10 by this query:
SELECT
attendance_in.EDatetime,
members_info.mfullname,
attendance_out.ODatetime
FROM
attendance_in
LEFT JOIN members_info ON members_info.id = attendance_in.MemID
LEFT JOIN attendance_out ON attendance_out.MemID = attendance_in.MemID
WHERE date(attendance_in.EDatetime) OR date(attendance_out.ODatetime) = "2014-03-10"
But it give me different results in Attendace_out Results
You have a mistake in your query.
You wrote:
WHERE date(attendance_in.EDatetime) /* wrong! */
OR date(attendance_out.ODatetime) = "2014-03-10"
This is wrong, as the first expression date(attendance_in.EDatetime) always evaluates to true.
You may want
WHERE date(attendance_in.EDatetime) = "2014-03-10"
OR date(attendance_out.ODatetime) = "2014-03-10"
But, this is guaranteed to perform poorly when your attendance_in and attendance_out tables get large, because it will have to scan them; it can't use an index.
You may find that it performs better to write this:
WHERE (attendance_in.EDatetime >='2014-03-10' AND
attendance_in.EDatetime < '2014-03-10' + INTERVAL 1 DAY)
OR (attendance_out.EDatetime >='2014-03-10' AND
attendance_out.EDatetime < '2014-03-10' + INTERVAL 1 DAY)
That will check whether either the checkin our checkout time occurs on the day in question.
I have a system that shows records year wise. I have dropdown menu from which user selects year, and I am storing that value in variable $year. So now when $year = 2013-2014, it should not display records of year 2014-2015. BTW when I insert my contractNumber, I also insert the year which user has selected during the login. e.g. contractNumber = 1#2013-2014.
I tried this queries:
SELECT * FROM contract WHERE contarctNumber RLIKE "^$year";
Now when I select year 2014-2015, it still displays all the records from year 2013-2014.
Any suggestions?
Try this query
SELECT * FROM contract WHERE contarctNumber LIKE "%$year";
SQLFiddle DEMO
Example
CREATE TABLE test (contarctNumber varchar(25));
INSERT INTO test VALUES ('1#2013-2014'), ('1#2014-2015'), ('2#2014-2015');
Select Query
SELECT * FROM test WHERE contarctNumber LIKE "%2014-2015";
Output
| CONTARCTNUMBER |
------------------
| 1#2014-2015 |
| 2#2014-2015 |
If the contractNumber always end in the date range, why not use:
SELECT * FROM contract WHERE contarctNumber LIKE "%$year";
This means it will match anything before the $year selected but still match the range specified.
Option #2:
SELECT * from contract where RIGHT(contarctNumber, 9) = '$year';
I want to know how to display report by month using PHP and Mysql
Example of Report on the web page:
January 2011
==============
Store Name | Total Order Cost
SHOP A | £123
SHOP B | £100
February 2011
==============
Store Name | Total Order Cost
SHOP A | £123
SHOP B | £100
SHOP C | £99.40
I have mysql tables
tbl_shop
ShopID
ShopName
tbl_order
OrderID
ShopID
OrderDate
Total
You will need to iterate trough the result of the query and create an multidimensional array using the month/year combination as keys. The query below should be a good indication on how to fetch the required information from your database.
SELECT
MONTH(to.OrderDate),
YEAR(to.OrderDate),
SUM(to.Total),
to.*
FROM tbl_order as to
INNER JOIN tbl_shop as ts ON ts.ShopID = to.ShopID
GROUP BY to.ShopID, MONTH(to.OrderDate), YEAR(to.OrderDate)
Note that I havn't tested this query - please handle it as pseudo-code. You might need to throw around the GROUP BY fields a little and test if it works.
Use
SELECT ShopName,SUM(Total),MONTHNAME(OrderDate) from tbl_shop
left join tbl_order
on tbl_shop.ShopID = tbl_order.ShopID
GROUP By(ShopID),MONTHNAME(OrderDate)
will give you All months report.
Use this query:
SELECT monthname(o.OrderDate) as Month, year(o.OrderDate) as Year,
s.ShopName, sum(o.Total) as Total
FROM tbl_Shop s JOIN tbl_Order o
ON s.ShopID=o.ShopID
GROUP BY o.shopID,year(o.Orderdate),month(o.Orderdate)
ORDER BY year(o.OrderDate),month(o.OrderDate)
then for every row from result if month+year has changed (a variable $last_date could help) then print
$Month $Year
==============
Store Name | Total Order Cost
$ShopName | $Total
else print
$ShopName | $Total