I have 3 data with the same name fields but with different values
id | name | date
------ | ------ | -----------
1 | john | 2015-10-02
2 | john | 2016-09-10
3 | john | 2017-08-10
I want to combine into a single three value fields by name, and its value appears by fields year 2015, year 2016, year 2017. like the example below
id | name | 2015 | 2016 | 2017
------ | ------ | ----------- | ------------ | -----------
1 | john | 2015-10-02 | 2016-09-10 | 2017-08-10
I tried using group_by but only 1 field values that appear.
This my models.
function viewkal() {
$this->db->order_by('name','ASC');
$this->db->group_by('name');
$query = $this->db->get('mytabel');
return $query->result();
}
You should use an aggegation function like max or min for grouped by function
$this->db->select_max('date 1');
$this->db->select_max('date 2');
$this->db->select_max('date 3');
You can use a custom SQL query for this. Something like this will group concatente the fields:
SELECT name,
GROUP_CONCAT(date1 SEPARATOR '') AS date1,
GROUP_CONCAT(date2 SEPARATOR '') AS date2,
GROUP_CONCAT(date3 SEPARATOR '') AS date3
FROM `mytable` GROUP BY name
We define the separator to be none, else we will have commas around the fields. This method works for string and date fields.To use a custom query in CodeIgniter pass the query to:
$this->db->query("YOUR QUERY");
Related
I have a table prices with where I store more times in a day more values referred to a customer like this:
Table prices:
| id | customer_id | value_1 | value_2 | value_3 | created_at |
-------------------------------------------------------------------------
| 1 | 10 | 12345 | 122 | 10 | 2021-08-11 10:12:40 |
| 2 | 10 | 22222 | 222 | 22 | 2021-08-11 23:56:20 |
| 3 | 12 | 44444 | 444 | 44 | 2021-08-12 08:12:10 |
| 4 | 10 | 55555 | 555 | 55 | 2021-08-13 14:11:20 |
| 5 | 10 | 66666 | 666 | 66 | 2021-08-13 15:15:30 |
| 6 | 10 | 77777 | 777 | 77 | 2021-08-13 16:12:50 |
I have some filters on that table to retrieve only records with date greater than X and/or lower than Y, sort records by value_1 or value_2, etc...
With that filters I have to take only 1 record for each day of a customer specified.
I'm able to get the record with the highest value_1 for example, by using sql function max() and group by date.
// Init query
$query = Price::query();
// Take the greatest value of value1
$query = $query->selectRaw(
'max(value_1) as highest_value_1, ' .
'date(created_at) as date'
);
// If defined, add a greater or equals
if ($from) $query->where("created_at", ">=", $from);
// If defined add a lower or equals
if ($to) $query->where("created_at", "<=", $to);
// Get results for current customer only, grupping by date and ordering it
$query = $query->where('customer_id', $id)->groupBy('date')
->orderBy('date', 'DESC');
// Fetch records
$records = $query->get();
But now I would like to have only the last record for each day of a customer specified.
I need an eloquent/sql solution because the date range to search may be large and the table has a lot of records.
How can I archive that?
Thanks
Not a complete solution (no customer filter nor laravel use), but I would use something like that in pure sql :
SELECT
CONCAT(EXTRACT(YEAR_MONTH FROM created_at),EXTRACT(DAY FROM created_at)) AS day,
MAX(created_at)
FROM mytable
GROUP BY day;
Of course, you may use other function to group by day (like string regexp or substr).
I have a MySQL table:
+======+=========+============+======+======+
| name | surname | other_name | year | date |
+======+=========+============+======+======+
| John | Foo | NULL | 2000 | 2017 |
+------+---------+------------+------+------+
| John | Foo | Bar | 2000 | 2018 |
+------+---------+------------+------+------+
| John | Bar | NULL | 2000 | 2018 |
+------+---------+------------+------+------+
| John | Bar | Bar | 2000 | 2018 |
+------+---------+------------+------+------+
| John | Foo | NULL | 1990 | 2018 |
+------+---------+------------+------+------+
I'm trying to group the records for same person. Same person is identified by name, surname and year of birth.
One can however change his surname (Foo -> Bar). Then the old rows' other_name column should be updated with the new name. Unfortunately the data I have are incomplete and when one changed his name, the other_name might have been updated, but it also might not.
I can easily group by the three basic columns.
What I need to do as well though is to cross compare the surname and other_name and if they match and so do the name and year columns, group them under the most recent surname (decided by date when the row was recorded).
The final print result should look like this:
+======+===========+======+
| name | surname | year |
+======+===========+======+
| John | Bar (Foo) | 2000 |
+------+-----------+------+
| John | Foo | 1990 |
+------+-----------+------+
I realize it's rather a complex task for an SQL query. So if you have a simpler solution accomplished in the program (PHP), I would appreciate it as well.
Hmmm . . . This does what you want in the limited case that surnames are only changed once:
select t.name, t.year, group_concat(distinct t.surname) as surnames
from t left join
t tother
on t.surname = tother.other_name and t.name = tother.name and t.year = tother.year
group by t.name, t.year, coalesce(tother.surname, t.surname);
Here is a db<>fiddle (it uses Postgres because I find that easier to set up but all is the same except the group_concat()).
Example my_table
ID | Name | Date
--------------------------
12 | John | 123456789
13 | Mike | 987654321
...
29 | Rick | 123498765
30 | Adam | 987651234
show output result like this
Month | Count
--------------------------
3 | 5 |
6 | 8 |
How can I do this with PHP?
You can do this using MySQL Query as below.
SELECT MONTH(FROM_UNIXTIME(`Date`)) `Month`
,COUNT(ID)
FROM my_table
GROUP BY `Month`;
Since post tagged codeigniter
This is codeigniter way:
$query = $this->db->select("month(from_unixtime(`Date`)) as `month`, count(1) as `count`",FALSE)
->group_by("month");
->get("your_table");
I'm struggling on how to write this query and cant quite find an answer to help me with my case.
Consider the following table:
-----------------------------------------------
| ID | Value1 | Value2 | Value3 | Date |
-----------------------------------------------
| 1 | 10 | 23 | 30 | 2015-01-01 |
-----------------------------------------------
| 1 | 11 | 33 | 40 | 2015-02-01 |
-----------------------------------------------
| 2 | 26 | 93 | 20 | 2015-01-01 |
-----------------------------------------------
| 2 | 11 | 33 | 50 | 2015-02-01 |
-----------------------------------------------
I want to retrieve the average value of Value1 where the Date is 2015-01-01
I thought that
SELECT AVG(PAM_1) FROM MyTable WHERE DATE = 2015-01-01
would work but of course it does not. I'm aware that I probably need to use HAVING but I'm being confused if I must also use GROUP BY and if do I need the AS (something) part.
EDIT
The problem was not related to the query. I was supplying the date trough a variable as such:
$sth = $db->prepare("SELECT AVG(Value1) FROM MyTable WHERE DATE = $date");
Which is not possible to do with prepared statements.
Your query is basically fine. Your date constant is not. Dates constants should be enclosed in single quotes:
SELECT AVG(PAM_1)
FROM MyTable
WHERE DATE = '2015-01-01';
If the date could have a time component, then the following is the best way to handle this:
SELECT AVG(PAM_1)
FROM MyTable
WHERE DATE >= '2015-01-01' AND DATE < '2015-01-02';
I have two table:
Name
id | name | city_id
1 | aaa | 1
2 | vvv | 2
3 | ddd | 2
4 | sss | 3
5 | dds | 1
etc
City:
id | name
1 | London
2 | NY
3 | Boston
etc
how can i get City and count:
name_city | count
London | 2
NY | 2
Boston | 1
In City table:
$q = $this->createQuery('a')
->leftJoin('a.Name n')
->select('a.name_city as name_city, sum(n.city_id) as sum');
return $q->execute();
but this is wrong.
You should use count() instead of sum(), and plus, you need a group by.
You do not appear to have a FROM clause, the object type is not specified for the a entity.
Also, read the aggregate values section in the documentation.
this post was kinda helpful but I though that I would add a little more details for anyone looking to join 2 tables and with an aggregate count.
e.g. this post (http://stackoverflow.com/questions/7837671/mysql-join-tables-and-count-instances) but in doctrine.
Using the example above the query would be (doctrine 2.0):
$q = $this->em->createQueryBuilder('a')
->select('a.name_city as name_city, count(n.city_id) as sum');
->from('city','a')
->leftJoin('a.Name n')
->groupBy('n.id')
->orderBy('sum')
$query = $qb->getQuery();
echo $qb->getDql(); // if you want to see the dql created
$result = $query->getResult();