COUNT with active record? - php

I use in a database. but I want to use in CodeIgniter. How can I do this with CodeIgniter using the active record query method? Can this be done with COUNT po_id?
SELECT position.po_name AS position, activity.ac_name AS activity ,
COUNT(register.po_id) AS regis FROM register
INNER JOIN activity ON register.ac_id = activity.ac_id
INNER JOIN position ON register.po_id = position.po_id
WHERE register.regis_status = 2 AND activity.ac_id = 2
GROUP BY register.ac_id,register.po_id
regis_status | ac_id | po_id
-----------------------------
2 | 4 | 2
2 | 2 | 2
2 | 2 | 2
3 | 2 | 2
3 | 2 | 2
1 | 3 | 2
2 | 3 | 1
1 | 7 | 2

If the query is correct .Try this
$this->db->select('position.po_name AS position, activity.ac_name AS activity , COUNT(register.po_id) AS regis')
->from('register')
->join('activity', 'register.ac_id = activity.ac_id','INNER')
->join('position ', 'register.po_id = position.po_id','INNER')
->where('register.regis_status', 2)
->where('activity.ac_id', $ac_id)
//more where ->where()
->group_by('register.ac_id,register.po_id');

Related

Select all possible rows even if value doesn't exist on JOIN

I'm trying to create a permission system but I'm not able to select all the possible options I have on the database. For example, considering I have the following tables on my database:
tb_group
id | group | slug
1 | Admin | admin
2 | Manager | manager
3 | Store Manager | store-manager
4 | Secretary | secretary
tb_area
id | area
1 | products
2 | users
3 | categories
4 | purchases
tb_permission
id_store | id_group | id_area | access | add | edit | remove
2 | 2 | 1 | 1 | 0 | 0 | 0
2 | 2 | 3 | 1 | 1 | 1 | 0
The expected result I want is to get all the possible permissions (access, add, edit, remove) for all possible areas from an specific group. So I would have this end result:
id_store | id_group | area | access | add | edit | remove
2 | 2 | products | 1 | 0 | 0 | 0
2 | 2 | users | 0 | 0 | 0 | 0
2 | 2 | categories | 1 | 1 | 1 | 0
2 | 2 | purchases | 0 | 0 | 0 | 0
So, even if I don't have any registers on table tb_permission for group 2 and areas 2 and 4, I want to have them on the query result with null or 0 values.
This is the code I have currently, but it only displays the result if the area exists on the tb_permission table.
SELECT
tp.access, tp.add, tp.edit, tp.remove,
ta.area,
tg.slug
FROM tb_permission tp
LEFT JOIN tb_area ta
ON ta.id = tp.id_area
LEFT JOIN tb_group tg
ON tg.id = tp.id_group
WHERE tp.id_store = 2
So I want to get all permissions the group number 2 has and also all the ones this group still has no register on the database. But my query is only returning the ones that is already on the database. Is it possible to get the result I expect with a single query?
You need to LEFT JOIN with tp_permission. Put the condition of tp.id_store = 2 in the ON condition so it doesn't filter out the non-matching rows.
You can CROSS JOIN the group and area tables to get all combinations.
SELECT 2 AS id_store, tg.id AS id_group, ta.area,
IFNULL(tp.access, 0) AS access,
IFNULL(tp.add, 0) AS add,
IFNULL(tp.edit, 0) AS edit,
IFNULL(tp.remove, 0) AS remove
FROM tb_group AS tg
CROSS JOIN tb_area AS ta
LEFT JOIN tb_permission AS tp
ON ta.id = tp.id_area AND tg.id = tp.id_group AND tp.id_store = 2
WHERE tg.id = 2

SQL query to return combined data of all rows that don't belong to current user

Imagine this is my table:
----------------------------------------------------
| id | user_id | amount_1 | amount_2 | amount_3 |
----------------------------------------------------
| 1 | 1 | 2 | 3 | 4 |
----------------------------------------------------
| 2 | 2 | 2 | 1 | 1 |
----------------------------------------------------
| 3 | 2 | 1 | 2 | 2 |
----------------------------------------------------
| 4 | 3 | 2 | 1 | 4 |
----------------------------------------------------
I need a query that gives me one result set for every entry that belongs to my current user, and then returns everything else as a single combined row with the amounts summed.
So in this case if I am user 1, I should get the following rows back:
---------------------------------------
| id | amount_1 | amount_2 | amount_3 |
---------------------------------------
| 1 | 2 | 3 | 4 | my own amounts
---------------------------------------
| 2 | 5 | 4 | 7 | everyone else's amounts
---------------------------------------
Any tips?
I've considered it might be a better idea to just filter the data in the code (php). Please help i'm starting to hate myself
You could use a UNION in sql
select 1 id, amount_1, amount_2, amount_3
from my_table
where user_id = 1
union
select 2 , sum(amount_1) , sum(amount_2), sum(amount_3 )
from my_table
where user_id <> 1
You can do with one query using union:
SELECT user_id, amount_1, amount_2, amount_3
FROM table
WHERE user_id = YOUR_USER_ID
UNION
SELECT -1, SUM(amount_1) AS amount_1, SUM(amount_2) AS amount_2, SUM(amount_3) AS amount_3
FROM table
WHERE user_id != YOUR_USER_ID
You can use aggregation in one fell swoop:
select (case when user_id = 1 then id end) as my_user_or_not,
sum(amount_1), sum(amount_2), sum(amount_3)
from t
group by my_user_or_not;
The null values in the first column indicate another user. You have labelled the column id, which is a bit problematic if you were -- for instance -- to choose user_id = 2 in your example. NULL seems safer for this purpose.

SQL: get data spread over 3 tables

I am trying to get some statistics for an online game I maintain. I am searching for an SQL statement to get the result on the bottom.
There are three tables:
A table with teams, each having a unique identifier.
table teams
---------------------
| teamid | teamname |
|--------|----------|
| 1 | team_a |
| 2 | team_x |
---------------------
A table with players, each having a unique identifier and optionally an affiliation to one team by it's unique teamid.
table players
--------------------------------
| playerid | teamid | username |
|----------|--------|----------|
| 1 | 1 | user_a |
| 2 | | user_b |
| 3 | 2 | user_c |
| 4 | 2 | user_d |
| 5 | 1 | user_e |
--------------------------------
Finally a table with events. The event (duration in seconds) is related to one of the players through their playerid.
table events.
-----------------------
| playerid | duration |
|----------|----------|
| 1 | 2 |
| 2 | 5 |
| 3 | 3 |
| 4 | 8 |
| 5 | 12 |
| 3 | 4 |
-----------------------
I am trying to get a result where the durations of all team members is summed up.
result
--------------------------
| teamid | SUM(duration) |
|--------|---------------|
| 1 | 14 | (2+12)
| 2 | 15 | (3+8+4)
--------------------------
I tried several combinations of UNION, WHERE IN, JOIN and GROUP but could not get it right. I am using PostgreSQL and PHP. Can anyone help me?
Just use sum with group by:
select t.teamid, sum(e.duration)
from team t
join players p on t.teamid = p.teamid
join events e on p.playerid = e.playerid
group by t.teamid
If you need all teams to be returned even if they don't have events, then use an outer join instead.
Try this
SELECT teamid, Sum(duration),
AS LineItemAmount, AccountDescription
FROM teams
JOIN teams ON teams.teamid = players.teamid
JOIN events ON players.playersid = events.playersid
JOIN GLAccounts ON InvoiceLineItems.AccountNo = GLAccounts.AccountNo
GROUP BY teamid
http://www.w3computing.com/sqlserver/inner-joins-join-two-tables/

Select values from another table with most recent entry

I have 2 MySQL Tables:
Table with all Events
+----+---------------------+
| id | Eventtitle |
+----+---------------------+
| 1 | Event 1 |
| 2 | Event 2 |
| 3 | Event 3 |
| 4 | Event 4 |
+----+---------------------+
Table with user attend statuses - Users can change their status multiple times. Every time they change it, a new entry is inserted into the table
+----+------------+----------+---------+---------------------+
| id | event_id | user_id | status | attend_time |
+----+------------+----------+---------+---------------------+
| 1 | 1 | 2 | 1 |2013-07-03 15:34:02 |
| 2 | 1 | 2 | 2 |2013-08-03 19:01:02 | <--
| 3 | 3 | 1 | 1 |2013-07-03 15:34:02 |
| 4 | 4 | 4 | 3 |2013-07-03 15:34:02 |
| 5 | 4 | 6 | 2 |2013-07-03 15:34:02 |
| 6 | 4 | 6 | 1 |2013-07-03 18:55:02 | <--
+----+-----------------------+---------+---------------------+
Now I want all events listed and additionally the most recent attend state and attend_time of the currently logged in user (for example user_id 2 oder 54) - IF he is not in the attend table i still need an entry of the event. (in that case a NULL for the state and attend_time would be good)
Here I rebuild the Data Structure: http://sqlfiddle.com/#!2/c1b3f
IF there is no way on how to get the result with MySQL - I will try to get it with PHP
Try something like this:
SELECT s.id, eventtitle, status, attend_time
FROM events e
JOIN status s ON e.id = s.event_id
WHERE user_id = 2 AND attend_time = (SELECT MAX(attend_time) FROM status
WHERE user_id = 2)
SQLFiddle
Or:
SELECT s.id, eventtitle, s.status, s.attend_time
FROM events e
JOIN status s ON e.id = s.event_id
LEFT JOIN status s2 ON s.attend_time < s2.attend_time
WHERE s.user_id = 2 AND s2.attend_time IS NULL
SQLFiddle
(not tested)
SELECT a.id, eventtitle, status, attend_time FROM events b JOIN status a ON b.id = a.event_id WHERE user_id = 2 order by attend_time desc

selecting a set of rows with specific record data

I here today with a question that has left me rather confused and puzzled. Perhaps someone out there could give me a bit of assistance.
I have three table as followed. Please note that they are simplified for this question.
//table_checks//
check_id |task_id| status
1 | 1 | Done
2 | 1 | Done
3 | 1 | Done
4 | 2 | Done
5 | 2 | Not Done
6 | 2 | Not Done
7 | 2 | Not Done
8 | 2 | Done
9 | 3 | Done
10 | 3 | Done
11 | 3 | Not Done
12 | 3 | Done
//table_user//
user_id | email | type
1 | a#a.com | IN
2 | b#b.com | IN
3 | c#c.com | EX
//table_chk_usr//
check_id |user_id
1 | 1
2 | 1
3 | 1
4 | 2
5 | 2
6 | 2
7 | 2
8 | 2
9 | 3
10 | 3
11 | 3
12 | 3
Here are three tables with its relation in the table_chk_usr table.
My question is how do I query and select rows of table_user with type 'IN' from table table_user where all of users assigned task_ids in the table_checks are with the status = done.
So the expected result should be as follows
//table_user//
user_id | email | type
1 | a#a.com | IN
Since user_id with 1 has completed all task_ids with status done.
I hope this makes sense to those of you who are reading. Any help will be much appreciated.
Please Note that I am using PHP as my server side language, if that helps in any way.
I think this is what you are looking for.
select user.user_id, user.email, user.type,
sum(if(status = 'done',1, 0)) as done, count(*) as checks
from checks
join chk_user on checks.check_id = chk_user.check_id
join user on chk_user.user_id = user.user_id
group by chk_user.user_id
having done = checks
sqlFiddle
You could use a join here, but there may be a better way to do it.
SELECT * FROM table_checks
INNER JOIN table_chk_usr
ON table_checks.check_id = table_chk_usr.check_id
INNER JOIN table_user
ON table_chk_usr.user_id = table_user.user_id
WHERE table_checks.status = 'Done'
AND table_user.type = 'IN'

Categories