PHP MySQL multiple count join addition - php

I have searched high an low for a solution, but I just can't get my head wrapped around how to set this up.
I have a table called "cals". It contains a column called "rep_code". Which contains a certain value identifying the cal, ie. "EFM","LM" etc. The "cals" list of records are linked to wells by "well_id" which is the indexer on another table called "wells". Now each record in the wells table is linked by "run_id" which is the indexer on another table called "runs".
Wells table:
Indexer | run_id
1 | 5
2 | 3
3 | 5
4 | 2
cals table:
Indexer | well_id | rep_code
1 | 3 | LM
2 | 4 | EFM
3 | 1 | LM
4 | 3 | EFM
Now when I view the list of runs, I want to display the total number reports in the run that have "EFM" under "rep_code", and total number of "LM" codes etc. So on the list of runs, the run with ID of 5 should say total of 2 "LM" reports and 1 "EFM". Run number 2 should just have 1 "EFM and 0 "LM"
Basically, what I think I need to do is " Join wells into cals adding run_id where well_id = $well_id from run list"...I think, every time I read this I get a little confused. I am new to "join" so I apologize.
I have managed to put together this bit of code to count each occurrence which works for one well, but cannot seem to get my head wrapped around putting it all into a functional statement for all wells in the run.
$sql = "SELECT
COUNT(CASE WHEN rep_code='LM' THEN 1 END) AS LM_tot,
COUNT(CASE WHEN rep_code='EFM' THEN 1 END) AS EFM_tot,
COUNT(CASE WHEN rep_code='GM' THEN 1 END) AS GM_tot
FROM cals WHERE well_id = '$well_id'";
$query = #mysql_query($sql);
$result = #mysql_fetch_array($query);
$LM_tot = $result['LM_tot'];
$EFM_tot = $result['EFM_tot'];
$GM_tot = $result['GM_tot'];
I also started this join, but I haven't gotten it to work yet.
sql = "SELECT
COUNT(CASE WHEN rep_code='LM' THEN 1 END) AS LM_tot,
COUNT(CASE WHEN rep_code='EFM' THEN 1 END) AS EFM_tot,
COUNT(CASE WHEN rep_code='GM' THEN 1 END) AS GM_tot
FROM cals, wells INNER JOIN wells ON cals.well_id = wells.indexer
WHERE run_id = '$run_id'";
I hope I have explained this clear enough.

Putting apart the join you are talking to put your query to work you just need to change a bit:
$sql = "SELECT
SUM(CASE WHEN rep_code='LM' THEN 1 ELSE 0 END) AS LM_tot,
SUM(CASE WHEN rep_code='EFM' THEN 1 ELSE 0 END) AS EFM_tot,
SUM(CASE WHEN rep_code='GM' THEN 1 ELSE 0 END) AS GM_tot
FROM cals
INNER JOIN
wells ON cals.well_id = wells.indexer
WHERE cals.well_id = '$well_id'";
If there more things to add, update your question with your tables structure and put some example data and the desired result, then I will update my answer.

This is what i ended up using, and works great.
$sql = "SELECT
COUNT(CASE WHEN rep_code='LM' THEN 1 END) AS LM_tot,
COUNT(CASE WHEN rep_code='EFM' THEN 1 END) AS EFM_tot,
COUNT(CASE WHEN rep_code='GM' THEN 1 END) AS GM_tot
FROM cals
INNER JOIN
wells ON cals.well_id = wells.indexer
WHERE run_id = '$run_id'";

Related

SQL query not equal to operator not working, with JOIN

I wonder if someone could help me with an SQL query.
I am trying to display all results except where in Table 2 both the userid column equals 1 and the hidden column equals 1.
I am basically trying to hide results from individual users based on their id and the value in the hidden column either 1 or empty.
I have so far managed to make a query that does the opposite and can't figure out how to change it. I have tried adding !=, <>, NOT and a few other things, but nothing is working for me!
Here is the query I am working with.
$stmt = $conn->prepare("SELECT tl.id, tl.name, tl.locale, uh.hidden
FROM theList AS tl
LEFT JOIN user_hidden_list AS uh ON uh.est_id = tl.id
WHERE uh.userid = '1' AND uh.hidden = '1'");
How do I display all results expect those with a uh.userid = 1 and uh.hidden = 1
UPDATE: Tables
Table: user_hidden_list
userid | Hidden | est_id
---------------------------
1 | 1 | 1
2 | 1 | 1
1 | 1 | 2
Table: theList
id | name | locale
------------------------
1 | Jacks | LDN
2 | MacD's | LDN
3 | BK | LDN
4 | Byron | LDN
So if I am logged in with and userid of:
1 I should see: BK and Byron.
2 I should see: MacD's, BK and Byron.
3 (or anything else) I should see: Jacks, MacD's, BK and Byron.
If i understood correctly, the table user_hidden_list mantains a relation between one user and the users he can't see. So for, example, user with id equal to 1 (matching on column userid) can't see users 1 and 2 (matching on column est_id).
So, for a particular user with ID = X, we can get the ID list of user he can't see like next:
SELECT
est_id
FROM
user_hidden_list
WHERE
userid = X AND hidden = 1;
Using the previous query, we can get the visible users for user X like on next query:
SELECT
tl.id, tl.name, tl.locale
FROM
theList AS tl
WHERE
tl.id NOT IN (SELECT est_id
FROM user_hidden_list
WHERE userid = X AND hidden = 1);
I'm sure there will be a better (elegant) way to do this, but i'm just leaving work and my mind is not working nice now.
I am trying to display all results except where in Table 2 both the userid column equals 1 and the hidden column equals 1.
This does not suggest an outer join. You seem to want:
SELECT tl.id, tl.name, tl.locale, uh.hidden
FROM theList tl JOIN
user_hidden_list uh
ON uh.est_id = tl.id
WHERE NOT (uh.userid = 1 AND uh.hidden = 1);
I am guessing that userid and hidden are numbers of some sort, so I removed the single quotes. If they are really strings, then use the single quotes.
This also assumes that these values cannot be NULL. If that is a possibility, then the logic can be adjusted (using the null-safe comparator <=>).
Try out this, with even parantheses:
SELECT tl.id, tl.name, tl.locale, uh.hidden
FROM theList tl JOIN
user_hidden_list uh
ON uh.est_id = tl.id
WHERE (uh.userid <> 1 AND uh.hidden <> 1);

SQL Server Case with Session

I have an issue where I'm trying to show a result based on a time frame being either greater than 24 hours, greater than 18 hours or less than 18 hours where a My query thus far is written as
SELECT MAX(CASE WHEN DATEDIFF(HH,DATEADD(SECOND, inc.ORIGINATION_DATE, '19700101'),DATEADD(hour,6,GETDATE())) > 24 then 2
WHEN DATEDIFF(HH,DATEADD(SECOND, inc.ORIGINATION_DATE, '19700101'),DATEADD(hour,6,GETDATE())) > 18 then 1
Else 0 End) as DIFFERENCE
FROM dbo.HELP_DESK as inc
WHERE inc.LOGIN_ID in "some user"
and NOT EXISTS (SELECT work.Description from dbo.WORKLOG as work WHERE
work.INCIDENT_NUMBER = inc.INCIDENT_NUMBER
and work.WORK_LOG_TYPE = '16000'
and work.WORK_LOG_SUBMITTER in "User Group")
UNION ALL
SELECT MAX(CASE WHEN DATEDIFF(HH,DATEADD(SECOND, chg.ORIGINATION_DATE, '19700101'),DATEADD(hour,6,GETDATE())) > 24 then 2
WHEN DATEDIFF(HH,DATEADD(SECOND, chg.ORIGINATION_DATE, '19700101'),DATEADD(hour,6,GETDATE())) > 18 then 1
Else 0 End) as DIFFERENCE
FROM dbo.INFRASTRUCTURE_CHANGE as chg
WHERE chg.ASLOGID in "some user"
and NOT EXISTS (SELECT work.Description from dbo.WORKLOG as work WHERE
work.CHANGE_ID = chg.CHANGE_ID
and work.WORK_LOG_TYPE = '31000'
and work.WORK_LOG_SUBMITTER in "User Group")
My output in this example is:
+------------+
| DIFFERENCE |
+------------+
| 2 |
| 2 |
+------------+
I have multiple values >24 so obviously due to the union Im showing two separate values correctly as 2. However, what I want to do is somehow group them so I have a single output of 2, 1 or 0 that I can then output to a PHP session.
some form of count or group by both seem to fail unless I'm incorrectly grouping. There's also probably a better way of doing this but I appear to be taking the long road round.
Appreciate any pointers in taking me forward.
A simple change from UNION ALL to UNION returned the single result I was after to output a session value

Sum of value using condition in mysql

I have a table like this. Now i want two sum(hour).. 1 for place_type '1' and another for place_type '2'. Is it possible in mysql?
Now my query is
SELECT sum(hour) as totalHour from category_data group by category_data.user_id
also tried with IF condition but not working
SELECT IF(place_type='1',sum(hour),0) home,
IF(place_type='2', sum(hour), 0) center,
from category_data group by category_data.user_id
user_id place_type hour
1 1 2
1 2 5
2 1 3
2 2 4
3 1 2
Thanks in advance
Conditional aggregation is what you need here.
select sum(case when place_type = 1 then `hour` end),
sum(case when place_type = 2 then `hour` end)
from category_data
Example fiddle

Count users from table 2 in request to table 1

I have table with positions
tbl_positions
id position
1 Driver
2 Lobby
3 Support
4 Constructor
and in other table i have users
tbl_workers
id name position status
1 John 2 3
2 Mike 3 2
3 Kate 2 3
4 Andy 1 0
i do request of positions
Without status I select everything with this query .
SELECT p.id, p.position, count(*) FROM tbl_positions as p
inner join tbl_workers as w on w.position=p.id
group by p.id, p.position
But now i need output same query but also considers status, status 2=booked status, 3=placed. I need output like this in single query.
Position booked placed
Driver 0 0
Lobby 0 2
Support 1 0
Constructor 0 0
I tried add WHERE tbl_workers.status IN (2) for booked and WHERE tbl_workers.status IN (3) for placed and it works in two queries, but no luck joining this into one query
Try this:
SELECT p.id,
p.position,
SUM(CASE w.Status WHEN 2 THEN 1 ELSE 0 END) AS booked,
SUM(CASE w.Status WHEN 3 THEN 1 ELSE 0 END) AS placed
FROM tbl_positions AS p LEFT JOIN tbl_workers AS w
ON w.position=p.id
GROUP BY p.id, p.position
Although you can do this with a single SQL query, it may be more straightforward to handle this using PHP.
Use your current query and add status to the GROUP BY.
SELECT p.id, p.position, w.status, count(*) FROM tbl_positions as p
inner join tbl_workers as w on w.position=p.id
group by p.id, p.position, w.status
You'll get a result set like this:
position status count
Driver 2 0
Lobby 2 0
Support 2 1
Constructor 2 0
Driver 3 0
Lobby 3 2
Support 3 0
Constructor 3 0
Use PHP to logically determine 2 = booked and 3 = placed.

Help with limiting a joined mysql database query

I have written a query which returns all records with some many-to-many joins correctly for the entire set or an individual article using WHERE a.id = ?
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id
LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id
LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id
LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
BUT!
I've hit a brick wall trying to work out how to limit the articles to a specific number of IDs, for working with pagination.
I'm ideally trying to use as simple and clear SQL statements as possible because I'm using the codeigniter framework with their active record class.
http://codeigniter.com/user_guide/database/active_record.html
Would really appreciate some help as I don't want to revert to using multiple queries for this as I've tried to reduce it down to a single query for database efficiency.
Have search around and tried some alternatives but nothing seems to work. Many thanks!
For example the results I return are like this
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
2 test 2 2 1 1
2 test 2 1 2 1
2 test 2 1 1 2
2 test 2 5 1 1
2 test 2 8 1 1
2 test 2 1 4 1
2 test 2 1 4 2
I need the results like this so that I can create sub-arrays in the php like this:
$articles = $query->result_array();
$output = array();
foreach ($articles as $article) {
// set up article details
$article_id = $article['id'];
// add article details
$output[$article_id]['article_id'] = $article_id;
$output[$article_id]['date_added'] = $article['date_added'];
$output[$article_id]['title'] = $article['title'];
$output[$article_id]['content'] = $article['content'];
// set up people details and add people array with details if exists
if (isset($article['person_id'])) {
$person_id = $article['person_id'];
$output[$article_id]['people'][$person_id]['person_id'] = $person_id;
$output[$article_id]['people'][$person_id]['lastname'] = $article['lastname'];
$output[$article_id]['people'][$person_id]['firstname'] = $article['firstname'];
}
// set up organizations details and add organizations array with details if exists
if (isset($article['organization_id'])) {
$organization_id = $article['organization_id'];
$output[$article_id]['organizations'][$organization_id]['organization_id'] = $organization_id;
$output[$article_id]['organizations'][$organization_id]['organization_name'] = $article['organization_name'];
}
// set up categories details and add categories array with details if exists
if (isset($article['category_id'])) {
$category_id = $article['category_id'];
$output[$article_id]['categories'][$category_id]['category_id'] = $category_id;
$output[$article_id]['categories'][$category_id]['category_name'] = $article['category_name'];
}
}
But if I just use LIMIT (with offset etc) 1
the results I get are
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
instead of
---------------------------------------------------------------------
id title category_id person_id organization_id
---------------------------------------------------------------------
1 test 1 1 1
1 test 2 1 1
1 test 1 2 1
1 test 1 1 2
1 test 5 1 1
1 test 8 1 1
1 test 1 4 1
1 test 1 4 2
1 test 1 1 1
which is my desired result.
OK, so finally I worked out how it is possible.
Thought i'd include it here in case anyone else has the same problem.
Changing this line
FROM articles AS a
to this
FROM (SELECT * FROM articles LIMIT 5,3) AS a
does what I wanted.
So, why don't you use OFFSET 0,10 and LIMIT *number_of_results* in the SQL Query? (if I understood the question)
Specific number of IDs... WHERE ID IN (2,4,6,8)... ?
Are you using codeigniter's pagination?
http://codeigniter.com/user_guide/libraries/pagination.html
You can easily limit the number of records that are being returned using the MySQL LIMIT clause. This can be achieved like the following with your sample query.
SELECT a.id, date_added, title, content, category_id, person_id, organization_id, c.name AS category_name, firstname, lastname, o.name AS organization_name
FROM articles AS a
LEFT OUTER JOIN articles_categories AS ac ON a.id=ac.article_id LEFT OUTER JOIN categories AS c ON c.id=ac.category_id
LEFT OUTER JOIN articles_people AS ap ON a.id=ap.article_id LEFT OUTER JOIN people AS p ON p.id=ap.person_id
LEFT OUTER JOIN articles_organizations AS ao ON a.id=ao.article_id LEFT OUTER JOIN organizations AS o ON o.id=ao.organization_id
ORDER BY date_added
LIMIT 10
Where 10 is the number of records you wish to display. The MySQL LIMIT clause allows you to specify a limit of the number of records and an initial offset. Like so:
LIMIT <offset>,<limit>
In your case <offset> would be the current page * the number of records on a page. <limit> would be the number of records you would like to display per page.

Categories