Codeigniter count associated records between 2 tables - php

I have 2 database tables 'super_admin_staff' and 'super_admin_roles'
The staff table is made up like :
id
name
email
phone
role
The role table is made up like :
id
role
The id column from the roles table is unique and is associated with the 'roles' column of the staff table.
At the moment i am fetching all the roles from the database using model :
function superAdminStaffRoles()
{
$this->db->select('*');
$this->db->from('super_admin_roles');
$query = $this->db->get();
$result = $query->result();
return $result;
}
In my controller i pass it over to my view like this :
public function superAdminStaffRoles()
{
if ($this->isSuperAdmin() != true) {
$this->loadThis();
} else {
$this->load->model('super_admin_staff_model');
$data['userRecords'] = $this->super_admin_staff_model->superAdminStaffRoles();
$this->global['pageTitle'] = 'Staff Roles';
$this->global['pageDesc'] = 'Add or Edit new Staff Roles and Permissions';
$this->loadViews("super_admin/staff_roles", $this->global, $data, null);
}
}
then display the data in my view like :
<tbody>
<?php
if (!empty($userRecords)) {
foreach ($userRecords as $record) {
?>
<tr>
<td><?php echo $record->role ?></td>
<td>where want to loop through the association</td>
<td class="text-center">
<a class="btn btn-sm btn-info" href="<?php echo base_url() ?>/EditRole/<?php echo $record->id; ?>"><i class="fas fa-edit"></i></a>
<a class="btn btn-sm btn-danger deleteUser" href="<?php echo base_url() ?>/DeleteRole/<?php echo $record->id; ?>"><i class="fas fa-trash"></i></a>
</td>
</tr>
<?php
}
}
?>
</tbody>
How can i fetch the additional information i need in my model to display how many staff are associated with that role? i think i may need to join the tables and i don't have much knowledge on joins.
can it be done in the same query?
the result should be something like :
Staff table
|id | name | role |
.......................
|1 | staff1 | 1 |
|2 | staff2 | 1 |
|3 | staff3 | 2 |
|4 | staff4 | 3 |
|5 | staff5 | 3 |
Role Table
|id | role |
...............
|1 | role 1 |
|2 | role 2 |
|3 | role 3 |
and the result should look like :
|Staff Role | Assigned |
........................
| Role1 | 2 |
| Role2 | 1 |
| Role3 | 2 |
Any help appreciated

Here you go
First, you need to join the two tables
INNER JOIN
$this->db->from('super_admin_staff');
$this->db->join('super_admin_roles', 'super_admin_staff.role = super_admin_roles.id');
You'll get the following
|id | name | role |id | role |
......................................
|1 | staff1 | 1 |1 | role 1 |
|2 | staff2 | 1 |1 | role 1 |
|3 | staff3 | 2 |2 | role 2 |
|4 | staff4 | 3 |3 | role 3 |
|5 | staff5 | 3 |3 | role 3 |
LEFT JOIN
$this->db->from('super_admin_staff');
$this->db->join('super_admin_roles', 'super_admin_staff.role = super_admin_roles.id', 'left');
You'll get the following
|id | name | role |id | role |
......................................
|1 | staff1 | 1 |1 | role 1 |
|2 | staff2 | 1 |1 | role 1 |
|3 | staff3 | 2 |2 | role 2 |
|4 | staff4 | 3 |3 | role 3 |
|5 | staff5 | 3 |3 | role 3 |
|6 | staff6 | 0 |null| null |
GROUP BY
Then grouping (which is strongly associated with the select because what is in the select clause MUST be in the group by).
Here you want to group by the role, you can do by grouping with super_admin_staff.role, super_admin_roles.id or super_admin_roles.role.
As you want the super_admin_roles.role in the output, let's take it as grouping column.
Using COUNT(*) will return the number of rows for each group.
$this->db->select('super_admin_roles.role as StaffRole, COUNT(*) as Assigned');
$this->db->from('super_admin_staff');
$this->db->join('super_admin_roles', 'super_admin_staff.role = super_admin_roles.id');
$this->db->group_by('super_admin_roles.role');
$query = $this->db->get();

Related

Laravel impossible where query

I'm working on a filter for some products. I have the majority of it working however I am encountering an error with an impossible where clause.
The table contains multiple rows for a single product and I am trying to match multiple criteria per product, which is causing it to fail.
If you have an opinion on this, or possibly a way to fix this, I would greatly appreciate it.
The database table looks like this:
--------------------------------------------
|id | FilterKey | filterValue | product_id |
--------------------------------------------
|1 | Colour | Gunmetal | 1 |
|2 | Colour | Silver | 1 |
|3 | Size | 750cc | 1 |
|4 | Size | 1000cc | 1 |
|5 | Colour | Red | 2 |
|6 | Colour | Blue | 2 |
|7 | Size | 750cc | 2 |
|8 | Size | 1000cc | 2 |
--------------------------------------------
And the filter looks like this:
public function scopeFilterProduct($query, $filters)
{
$this->filters = $filters;
if (count ($this->filters) === 1 && isset($this->filters[0]))
{
return $query;
}
$query->join('product_filters', 'products.id', '=', 'product_filters.product_id')->Where(function($query){
foreach ($this->filters as $filter => $vals)
{
$this->filter = $filter;
$this->vals = $vals;
$query->Where(function ($query){
$query->Where('filterKey', $this->filter);
$query->Where(function($query){
foreach ($this->vals as $val){
$query->orWhere('filterValue', $val);
}
$this->vals = null;
});
});
$this->filter = null;
};
});
return $query;
}
This then outputs the following SQL statement:
select
distinct
`products`.`id`
, `product_id`
from
`products`
inner join
`product_filters`
on
`products`.`id` = `product_filters`.`product_id`
where
(
(`filterKey` = 'Colour' and (`filterValue` = 'gunmetal'))
and
(`filterKey` = 'Size' and (`filterValue` = '750cc'))
)
and
`products`.`deleted_at` is null
If selected, as in the screenshot, then only 'product one' should be present on the page.
The scope you have added in my opinion is wrong. Even your database structure is incorrect in my opinion. Here is how i would structure this:
Filters Table
This model will hold all the filter values. For example, Colour, Size etc. Here is how the filter table will be structured:
-----------------
|id | name |
-----------------
|1 | Colour |
|2 | Size |
-----------------
So your eloquent model become something like this:
class Filter extends Model
{
protected $fillable = ['id', 'name'];
public function products()
{
return $this->belongsToMany(Product::class, 'products_filters');
}
}
Products Table
Your product models becomes:
class Product extends Model
{
public function filters()
{
return $this->belongsToMany(Filter::class, 'products_filters');
}
}
products_filters Table
After the above changes, here is how the table will be structured:
--------------------------------------------
|id | filter_id | filterValue | product_id |
--------------------------------------------
|1 | 1 | Gunmetal | 1 |
|2 | 1 | Silver | 1 |
|3 | 2 | 750cc | 1 |
|4 | 2 | 1000cc | 1 |
|5 | 1 | Red | 2 |
|6 | 1 | Blue | 2 |
|7 | 2 | 750cc | 2 |
|8 | 2 | 1000cc | 2 |
--------------------------------------------
Now you can simply query the filters table, then get associated products for all filters. After that you simply need to compile a list of unique products.
Unqiue products based on selected filters.
$ids = [];
$products = new \Illuminate\Support\Collection();
foreach($filters as $filter) {
foreach($filter->products as $product) {
if(!in_array($product->id, $ids)) {
$ids[] = $product->id;
$products->push($product);
}
}
}
return view('results', compact('products'));
In your view, you need to write:
#foreach($products as $product)
// Your product block HTML
#endforeach

Query data from sql table where reference is in another table

I am using CodeIgniter and trying to query data from mysql.
Scenario -- Logged on user is Manager and wants to pull data for his team..
Explanation --
e_users table
|user_id | name | manager_id
---------------------------------
|1 | test | 10
|2 | another | 1
|3 | testX | 1
|4 | testY | 2
|5 | testX | 2
e_details table
|det_id | detail | user_id
---------------------------------
|1 | sdfs | 1
|2 | xcffgdf | 2
|3 | sdfsd | 3
|4 | etret | 5
|5 | cvbcvb | 5
Now when user_id 1 is logged as manager, he should get data of det_id -2,3 only,
e_details table have data and i want to query only those data of users where whose manager is currently logged on. Means manager will pull data of users from e_details table.
e_details table have user_id, detail_comment, details_date...
and e_users have user_id, manager_id , ...
I tried below function, but i could not get required data
$user_id = $this->session->userdata('user_id')
public function get_method($user_id)
{
$this->db->join('e_users', 'e_users.manager_id = e_details.user_id','INNER');
$this->db->where('e_details.user_id',$user_id);
return $this->db->get('e_details')->result_array();
}
I think i need to join two tables and then search with common key value?
Thanks,
Well If I am getting it correct you have missed the select statement.
This would help you
<?php
public function get_method($user_id){
$query = $this->db->select('e_users.*, e_details.*')
->from('e_users')
->join('e_details', 'e_users.user_id = e_details.user_id', 'inner')
->where('e_users.manager_id',$user_id)
->get();
if($query -> num_rows() > 0){
$details_array = $query->result();
print_r($details_array);die;
$response['details_array'] = $details_array;
return $response;
}else{
return false;
}
}
?>

PHP MySQL count events per location per user

I'm trying to build a query using data from 4 tables: Bookings, Users, Events, Locations
Bookings :
+---------------------------------+
|book_id | event_id | person_id |
+---------------------------------+
|1 | 1 | 2 |
|2 | 2 | 1 |
|3 | 2 | 2 |
|4 | 1 | 3 |
|5 | 3 | 1 |
|6 | 3 | 2 |
+---------------------------------+
Users :
+----------------------+
| user_id | name |
+----------------------+
| 1 | Joe |
| 2 | Jack |
| 3 | Jane |
+----------------------+
Events :
+------------------------+
| event_id | location_id |
+------------------------+
| 1 | 1 |
| 2 | 3 |
| 3 | 1 |
+------------------------+
Locations :
+---------------------------+
| location_id | name |
+---------------------------+
| 1 | Lombard |
| 2 | NYC |
| 3 | LA |
+---------------------------+
The query that I can't seem to write should get me to display a table like this :
+------------------------------+
+Name |Lombard|NYC|LA|Total|
+------------------------------+
+Joe |1 |0 |1 |2 |
+Jack |2 |0 |1 |3 |
+Jane |1 |0 |0 |1 |
+------------------------------+
+Totals |4 |0 |2 |6 |
+------------------------------+
What I got to work is displaying how many booking have been made per user but not per user AND per location using this query:
$query='
SELECT
bookings.person_id,
COUNT(bookings.person_id) AS total,
bookings.event_id,
users.display_name
FROM bookings
INNER JOIN users ON bookings.person_id=users.id
WHERE users.id=bookings.person_id
GROUP BY bookings.person_id';
$result = mysql_query($query);
if($result) {
while($row = mysql_fetch_array($result))
{
/* total bookings per user */
$value = $row['total'];
$sum += $value;
/* Displaying results */
echo "<tr width='500'>";
echo "<td>".$row['person_id']."</td>";
echo "<td>".$row['display_name']."</td>";
echo "<td>".$row['total']."</td>";
echo "</tr>";
}
This works okay and displays :
+-----------------------------------+
| ID | NAME | Total Bookings |
+-----------------------------------+
| 7 | Bob | 3 |
| 5 | Jane | 2 |
| 3 | Joe | 1 |
+-----------------------------------+
Could you please help me getting there. Thanks.
You are looking for a pivot table style query. Here's one way you can do it.
select u.name,
count(case when l.name = 'Lombard' then 1 end) as lombard,
count(case when l.name = 'NYC' then 1 end) as nyc,
count(case when l.name = 'LA' then 1 end) la,
count(u.name) total
from bookings b
inner join events e
on b.event_id = e.event_id
inner join locations l
on e.location_id = l.location_id
inner join users u
on u.user_id = b.person_id
group by u.name
with rollup
fiddle here
It gets a lot harder (and is generally easier to do in the application) if you dont know the possible column (location) values when you are writing the query.
http://sqlfiddle.com/#!9/92d50
SELECT u.name,
SUM(l.name = 'Lombard') lombard,
SUM(l.name = 'NYC') nyc,
SUM(l.name = 'LA') la,
COUNT(*) total
FROM bookings b
LEFT JOIN `events` e
ON b.event_id = e.event_id
LEFT JOIN locations l
ON e.location_id = l.location_id
LEFT JOIN users u
ON u.user_id = b.person_id
GROUP BY u.name
WITH ROLLUP

Multiple group in mysql

I have table, named "table_log".
Here is the structure
---------------------------------------
|id_log | user_id | login_date |
---------------------------------------
|1 | 1 |2014-09-02 14:58:53 |
|2 | 1 |2014-09-03 24:18:53 |
|3 | 1 |2014-09-02 14:58:53 |
|4 | 1 |2014-09-01 02:28:53 |
|5 | 2 |2014-09-04 01:48:53 |
|6 | 3 |2014-09-05 04:58:53 |
|7 | 2 |2014-09-06 03:58:53 |
----------------------------------------
I want to count number of user each days. not how much log is.
As an example data, I want to show it like this:
---------------------------
|date | user_number|
---------------------------
|2014-09-02 | 1 |
|2014-09-03 | 1 |
|2014-09-04 | 5 |
---------------------------
Does any can help me? How to query my database?
SELECT date(login_date) AS date, count(DISTINCT user_id) AS user_count
FROM table_log
GROUP BY date(login_date)
The date function gives just the date-part of a datetime column, then it's a simple group by.
I dont get your ques, but u expect it?
2014-09-03 there is one record how user number will come 4 ? which scenario u asking?
SELECT date(login_date) AS date, count(date(login_date))
FROM tbl
GROUP BY date(login_date)

pulling from a specific data from a row and column in a database

My data base looks like this.
its ordered ascending by NO#
And col2 is the start of the database NO# is basically invisible and only used as a reference as to row number
so lets say I wanted to display on a web page the text in col8, row 5. What would the php code be?
PS. the connect code is seperate and not an issue hence i did not include itI
-|NO#|col2|col3|col4|col5|col6|col7|col8|col9|col10
---------------------------------------------------
|1 | | | | | | | | | |
---------------------------------------------------
|2 | | | | | | | | | |
---------------------------------------------------
|3 | | | | | | | | | |
---------------------------------------------------
|4 | | | | | | | | | |
---------------------------------------------------
|5 | | | | | | |2012| | |
---------------------------------------------------
|6 | | | | | | | | | |
---------------------------------------------------
|7 | | | | | | | | | |
---------------------------------------------------
|8 | | | | | | | | | |
---------------------------------------------------
|9 | | | | | | | | | |
---------------------------------------------------
|10 | | | | | | | | | |
---------------------------------------------------
Here is my code but it whites out the page when I try to load it.
<?php
//selects row
$query = "SELECT * FROM `Inventory` WHERE NO# = '5'";
//select column
$col8 = $row['col8'];
// fetch the results
WHILE($row = mysql_fetch_array($query):
$row = mysql_fetch_array($result);
// display the results
<div id="year">echo "$col8";</div>
?>
I would probably do something like what's below. I have not tested this code, though.
<?php
$result = mysql_query( "SELECT `col8` FROM `Inventory` WHERE `NO#` = '5' LIMIT 1" );
$row = mysql_fetch_assoc( $result );
?>
<div id="year"><?php echo $row['col8']; ?></div>
Hopefully that'll help you out a bit.

Categories