Count How many Data in a month based on Criteria - php

I have 2 tables, master_kategori_project which is contain category of projects and project which is contains how many project in a specific month in a specific year. below is my master_kategori_project table.
id| category_project | description |
1 | Category 1 | descrip 1 |
2 | Category 2 | descrip 2 |
3 | Category 3 | descrip 3 |
and my project table look something like this
id| id_category_project | name_project | start_date |
1 | 1 | Project 1 | 27-01-2017 |
2 | 2 | Project 2 | 29-02-2017 |
i want to make a table that contain chart like this, u can see from the table on january i have 3 projects of kategori 1, 5 projects of kategori 2, 7 projects of kategori 3 and so on
how can i write an query that have something like this? the chart is automatically build by the table itself.
this is my model and i believe i did it wrong, because i can't put the data into the correct month
public function get_kategori_totals($mnth, $year=null)
{
$yr=date('Y');
$select = "
SELECT COUNT(category_project),start_date,category_project
FROM
project
LEFT JOIN
master_kategori_project
ON
project.id_category_project=master_kategori_project.id
WHERE
MONTH(start_date)='$mnth'".
(($year == null)?" AND YEAR(start_date)='$yr' GROUP BY category_project":"AND YEAR(stat_date)='$year' GROUP BY category_project");
return $this->db->query($select);
}

Use below query.
SELECT id_category_project, month(start_date), count(distinct name_project) as project_count
FROM project
WHERE start_date IS NOT NULL AND start_date <> '0000-00-00'
GROUP BY 1,2
ORDER BY 2,1

Related

How to select specific course by selecting course id and concatenate users all selected course with in same row

I am joining users table with selected_course table and course table with selected_course, my requirement is I want to get those users with course_id=2 and in same row select using concatenation of all courses which is selected by user.
user table
id name
1 user_1
2 user_2
user_education_details
id user_id education_id selected_course
1 1 1 2
2 2 1 2
3 1 2 4
4 3 1 2
5 3 2 4
Actual Requirement:
user_id required_course user_all_courses course_name
1 2 2,4 a,b
2 2 2 a
3 2 2,4 a,b
Using codeigniter query format:
$this->db->select('users.*');
$this->db->from('users');
$this->db->join('selected_course sc','c.user_id=users.id');
$this->db->join('course c','c.id=sc.selected_course');
$this->db->where('sc.selected_course',$course_id=2);
$this->db->get()->result();
A HAVING clause is what you're looking for. To filter data based on a group use this clause.
SELECT
ued.user_id,
2 AS required_course, -- passed course id
GROUP_CONCAT(ued.selected_course) AS user_all_courses,
GROUP_CONCAT(c.name) course_name
FROM user_education_details ued
INNER JOIN courses c ON ued.selected_course = c.id
GROUP BY user_id
HAVING SUM(IF(selected_course = 2, 1,0)) > 0;
Output:
| user_id | required_course | user_all_courses | course_name |
| 1 | 2 | 4,2 | b,a |
| 2 | 2 | 2 | a |
| 3 | 2 | 2,4 | a,b |
You can also order user_all_courses and course_name by using a ORDER BY clause inside GROUP_CONCAT. Here is one example.
GROUP_CONCAT(ued.selected_course ORDER BY selected_course ASC) AS user_all_courses,
Now you can quickly convert this to your equivalent CodeIgniter query.
Check this working fiddle for the same.

How to order data from database by user choice

Say i have this table :
---------+----------
name | id
---------+----------
apple | 1
orange | 2
book | 3
notebook | 4
textboo | 5
phone | 6
if the user want to sort this table as he want ..
not order them as id or name .. order them as he want to show them ..
How to make something like that ?
Can we do them by java or jquery or something else
if user want to display orange | 2 then phone | 6
then the other values or want to display notebook | 4 first then other values how we can control something like that ?
Suppose you have multiple users you will need to create a new table where you will save each user's sort order preferences.
---------+-------------------
item_id | user_id | sort
---------+------------------
1 | 1 | 2
2 | 1 | 1
3 | 1 | 3
After that you can easily use ORDER BY in your query to fetch the order chosen by the user based on his user_id. If you're looking for user_id = 1, the following query should work:
SELECT * FROM `table1` t1
LEFT JOIN `preferences_table` PT ON PT.item_id = t1.id
WHERE user_id = 1
ORDER BY PT.sort ASC

Php/mysql ranking system - Placement inside a result set ordered by column

In a blog-like website, all the users can "star" a news (= bookmark it, mark it as "favourite").
I have a mysql table for stats.
table_news_stats
id_news
total_stars (int) //Total number of users who starred this news
placement (int)
The placement field is intuitive: if you order all the news by the total_stars field you get each news placement. So, the news with most stars will be number 1, and so on.
So, suppose I have 700 records in my table_news_stats, and for each one I have the id and the total_stars count, how can I update the placement field automatically for each record? Which query is faster/better?
Example of the table_news_stats content:
First record (A):
1-3654-?
Second record (B):
2-2456-?
Third record (C):
3-8654-?
If you order the record by stars count:
the sequence of records is C - A - B
So... the result will be:
First record (A):
1-3654-2
Second record (B):
2-2456-3
Third record (C):
3-8654-1
Clarification:
why would I ever need the placement field at all?
It's pretty simple... the placement field will be populated by a cronjob the first day of every month. Basically it will provide a 'snapshot' of the rank of each news in terms of popularity (as it was at the beginning of the current month). As a consequence, thanks to the placement field, I will have the following information:
"The 1st day of this month the 'top starred' news list was like this:
1- News C
2- NewsA
3- News B "
Then, with a query "SELECT * FROM table_news_stats ORDER BY total_stars DESC" I can obtain the new ranking (in real-time).
As a consequence, I will have the following information:
"At the time the page is loaded, the 'top starred' news list is like this:
1- News A
2- News C
3- News B "
Finally, by comparing the two rankings, I obtain the last piece of information:
"News A has gained a position" +1
"News C has lost a position" -1
"News B has no change in position" +0
If there is a better way of doing this, let me know.
I guess you don't need to update the table just:
SELECT *
FROM table_news_stats
ORDER BY total_stars DESC
But if you want to know the place of each one you can:
SELECT *, IF(#idx IS NULL,#idx:= 1,#idx:= #idx+1)
FROM table_news_stats
ORDER BY total_stars DESC
And if you still need to update something like:
UPDATE table_news_stats
SET placement = FIND_IN_SET(id_news,(SELECT GROUP_CONCAT(t.id_news) FROM (SELECT id_news
FROM table_news_stats
ORDER BY total_stars DESC) t ))
SQLFiddle
Consider the following
mysql> select * from test ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 1 | 3 | 0 |
| 2 | 6 | 0 |
| 3 | 7 | 0 |
| 4 | 2 | 0 |
| 5 | 9 | 0 |
| 6 | 2 | 0 |
| 7 | 1 | 0 |
+------+-------------+-----------+
Now using the following you can update the placement as
update test t1 join
(
select *,
#rn:= if(#prev = total_stars,#rn,#rn+1) as rank ,
#prev:= total_stars
from test,(select #rn:=0,#prev:=0)r
order by total_stars desc
)t2
on t2.id = t1.id
set t1.placement = t2.rank ;
mysql> select * from test order by placement ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 5 | 9 | 1 |
| 3 | 7 | 2 |
| 2 | 6 | 3 |
| 1 | 3 | 4 |
| 4 | 2 | 5 |
| 6 | 2 | 5 |
| 7 | 1 | 6 |
+------+-------------+-----------+
Note that in case of tie will have the same placement.

reduction of each row in the table of database

i have a table temporary as follow as:
student | Data | number
-----------|---------------|--------------
1 | book | 2
1 | book | 5
1 | book | 9
2 | book | 1
2 | book | 5
i will show reduction of column in like as output column as follow as:
student | Data | number |output (number column of next row-previous line )
-----------|---------------|----------------|--------------
1 | book | 2 | 0
1 | book | 5 | 3 (result of (5-2=3)
1 | book | 9 | 4 (result of (9-5=4)
2 | book | 1 | 0
2 | book | 5 | 4 (result of (5-1=4)
how are writing of php's script is correct? because i'm confused
You didn't mention your DBMS, so this is standard SQL:
select student,
data,
number,
number - lag(number,1,number) over (partition by student order by id) as output
from the_table
order by student, id
SQLFiddle example
The following script will subtract the number from previous number for the same student. Here's how you can do it in MySQL (which doesn't support window functions.)
SELECT
t1.student,
t1.Data,
t1.number,
IF (t2.number IS NULL, 0, t1.number - MAX(t2.number)) as output
FROM
tbl t1
LEFT JOIN
tbl t2
ON
t1.student = t2.student
AND t1.number > t2.number
GROUP BY
t1.student, t1.Data, t1.number
Here's the SQL Fiddle

how to select all within a category if at least one falls within range

I'm using MySQL inside PHP.
I have an SQL table that looks something like this:
id | category_id | date
-----------------------------
1 | 3 | 2012-09-12
2 | 4 | 2012-10-25
3 | 3 | 2012-10-12
4 | 3 | 2012-10-02
5 | 4 | 2012-11-03
6 | 3 | 2012-11-02
I'm trying to figure out how can select all dates of the given category if at least one falls within the specified date range, otherwise select none.
For example:
If the date range is from 2012-09-01 to 2012-09-31, then the query should return all rows for category 3 and none for category 4.
Is there a way do this in a single query ?
Thanks!
You do this with a join or in clause:
select t.*
from t join
(select distinct category_id
from t
where date between <datefrom> and <dateto>
) tc
on t.category_id = tc.category_id
order by t.category_id, date

Categories