MYSQL count based off of two tables - php

Sorry for asking this, but I haven't found an answer to what I'm trying to do anywhere!
Basically, I have a database with two tables. Below or two examples I'll use:
Table 1:
Process ID Date
---------- -----------
1 2008/08/21
2 2008/08/23
3 2008/08/21
Table 2:
Process ID Qty
---------- ---
1 1
2 4
3 6
Basically, I was to do something in PHP where I will select table 1, and find all processes that occur today (in this example I'll say the 21st of August). I then want to take those process ids, and match them in Table two and give a count of their quantities.
The end result I'm trying to figure out in this example is how do I get the output to be "7" by using PHP to select the processes that happened today in one table, then add up the corresponding process quantities in another table.

SELECT sum(t2.qty)
FROM table1 t1
JOIN table2 t2 ON t1.pid = t2.pid
WHERE t1.date = '2008/08/21'

Related

SQL - Get data from 2 tables

I've read other threads about getting queries from 2 tables, but I still don't now how to implement my issue.
There is a Feed page where user gets queries from Table A sorted by date. And there is another Table B that contains some queries. I need to get queries from both tables, mix them, and sort by date.
Table A
----id---- ----date---- ----post----
1 20170514 post 1
2 20170512 post 3
3 20170510 post 5
Table B
----id---- ----date---- ----post---- ----thread----
1 20170513 post 2 1
2 20170511 post 4 2
SELECT * FROM tableA WHERE post!="" AND date!="" and SELECT * FROM tableB WHERE post!="" AND date!=""
Output (in plaint text to screen) should be:
table: Table A, post: post 1, date: 20170514
table: Table B, post: post 2, date: 20170513
table: Table A, post: post 3, date: 20170512
table: Table B, post: post 4, date: 20170511
table: Table A, post: post 5, date: 20170510
You can use UNION like this
SELECT id, date, post FROM TABLEA
WHERE date IS NOT NULL AND
post IS NOT NULL
UNION
SELECT id, date, post FROM TABLEB
WHERE date IS NOT NULL AND
post IS NOT NULL
you may need to use alias for the tables.
If you'd like to see a result-set containing both tables' rows, you should use JOIN but in this case, you should be able to connect those two tables. For example if you have a product table, and a product_details, then you should have a field on the second table like product_id which is pointing to an existing product's id. you can find out more here:
https://www.w3schools.com/sql/sql_join.asp
Otherwise you could try UNION which is used to combine two ore more result-ser of multiple SELECT statements:
https://www.w3schools.com/sql/sql_union.asp

Having max of column repeat for each row in mysql

Lets say I have a table A ,
A
user count
a 4
b 1
c 3
d 2
I want to write a query which returns each value of A along with max value of count,something like
user maxCount
a 4
b 4
c 4
d 4
The way I am trying to achieve this is,
select user,max(count) as maxCount from A
The result which I get is :
user maxCount
a 4
Which is clearly not what I want.
I understand I could write multiple queries(i.e. 'select user from A' /'select max(count) from A') as this may seem redundant ,
but I think having it this way would be best for me as I don't want to call mysql multiple times and also I push the returned data as a single jsonObj to the front end , so it is easier to have a single table then combing two returned-tables into one and than converting into json
This query will give you the max value on all rows:
SELECT user,
(SELECT MAX(count) FROM yourTable) AS maxCount
FROM yourTable;
Try this:
select user,max(count) as maxCount from yourTable group by user
That will get your your max counts, and group them by whatever unique values are in the user column.

Mysql conditions with grouping many-to-many tables

I was wondering if somebody can think of a more elegant solutions to my problem. I have trouble finding similar cases.
I have 5 tables. 3 are details for employees, skills and subskills. The remaining 2 are linking tables.
skill_links
skill_id subskill_id
1 4
1 5
2 4
2 6
emp_skill_links
employee_id subskill_id acquired
1 4 2013-04-05 00:00:00
1 5 2014-02-24 00:00:00
2 6 2012-02-26 00:00:00
2 5 2011-06-14 00:00:00
Both have many-to-many relations. Skills with subskills (skill_links) and employees with subskills (emp_skill_links).
I want to pick employees who have acquired all subskills for a skill. I tried doing it with one query, but couldn't manage it with the grouping involved. At the moment my solution is two separate queries and matching these in php array later. That is:
SELECT sl.skill_id, COUNT(sl.subskill_id) as expected
FROM skill_links sl
GROUP BY sl.skill_id
to be compared with:
SELECT sl.skill_id, esl.employee_id, COUNT(esl.subskill_id) as provided
FROM emp_skill_links esl
INNER JOIN skill_links sl
ON sl.subskill_id = esl.subskill_id
GROUP BY sl.skill_id, esl.employee_id
Is there a more efficient single query solution to my problem? Or would it not be worth the complexity involved?
If you consider a query consisting of sub-queries as meeting your requirement for "a more efficient single query solution" (depends on your definition of "single query"), then this will work.
SELECT employeeTable.employee_id
FROM
(SELECT sl.skill_id, COUNT(*) AS subskill_count
FROM skill_links sl
GROUP BY sl.skill_id) skillTable
JOIN
(SELECT esl.employee_id, sl2.skill_id, COUNT(*) AS employee_subskills
FROM emp_skill_links esl
JOIN skill_links sl2 ON esl.subskill_id = sl2.subskill_id
GROUP BY esl.employee_id, sl2.skill_id) employeeTable
ON skillTable.skill_id = employeeTable.skill_id
WHERE employeeTable.employee_subskills = skillTable.subskill_count
What the query does:
Select the count of sub-skills for each skill
Select the count of sub-skills for each employee for each main skill
Join those results based on the main skill
Select the employees from that who have a sub-skill count equal to
the count of sub-skills for the main skill
DEMO
In the is example, users 1 and 3 each have all sub-skills of main skill 1. User 2 only has 2 of the 3 sub-skills of main skill 2.
You'll note that the logic here is similar to what you're already doing, but it has the advantage of just one db request (instead of two) and it doesn't involve the PHP work of creating, looping through, comparing, and reducing arrays.

MySQL query with fallbacks (COALESCE) and JOINS

So I am having a hard time trying to write a single query for this. I have a table we will call table_a. I need to pull a single record that matches certain criteria. If the first one produces nothing then fall back to another one. I have been at this awhile and it very well could be something simple I am just missing.
SELECT COALESCE(ta.id,tb.id,0) AS theid,
FROM table_a
RIGHT JOIN (
SELECT table_a.id
FROM table_a
WHERE table_a.field_3='1' AND table_a.field_4='100' AND table_a.user_id='someidhere'
) AS ta
ON table_a.id = ta.id
RIGHT JOIN (
SELECT table_a.id
FROM table_a
WHERE table_a.field_5='2' AND table_a.field_4='100' AND table_a.user_id='someidhere'
) AS tb
ON table_a.id = tb.id
The problem with RIGHT JOIN is if the first one does not produce a record it will not go on to the next one, if I do LEFT JOIN it will pull all the records from table_a, if I specify WHERE table_a.user_id='someidhere' it will obviously pull all the records for that user. I am only looking for one. Essentially only field_3 and field_5 will be the ones that change. If I can not find something for field_3 it moves onto field_5. This will run on a table with 80k records. Thoughts?
Although a newbie, starting out with a cryptic example is not the greatest, but I'm trying here. Your query in itself is rather pointless on what it is doing. Its joining to itself to ultimately grab the ID of a thing that is for a certain user ID and field 4 value, but the field 3 or 5 should be a 1 or 2 respectively.
So, I've written the query directly to the "a" table for the user ID and field 4 which were common regardless of your right-join... THEN added an ( OR ) for your field 3 and 5 columns. This way, I only care about those of the 3 OR 5 value with same user/field 4 area. The ORDER BY clause will force that any record with the field 3 value of 1 is sorted first, then any that are field 5 = 2 will be secondary... So the final first record would be the '1' entry if one existed.
SELECT
table_a.id
FROM
table_a
where
table_a.user_id = 'someidhere'
AND table_a.field_4 = '100'
AND ( table_a.field_3 = '1'
OR table_a.field_5 = '2' )
order by
case when table_a.field_3 = '1'
then 1 else 2 end
So, if there are multiple records returned, you only need to care about the first one returned (in case there are two that qualify).

Best way to tell 3 or more consecutive records missing

I'm implementing a achievement system. One of the "badges" I'm trying to create will determine:
If a user has joined in at least one coding challenge
Then hasn't joined in 3 consecutive coding challenges
Then started participating again.
The badge is simply called "I'll be back" ;-)
The tables
users
==================
id fullname
1 Gary Green
challenge
==================================
id name start_date
1 challenge1 01-AUG-2010
2 challenge2 03-AUG-2010
3 challenge3 06-SEP-2010
4 challenge4 07-SEP-2010
5 challenge5 30-OCT-2010
6 challenge6 05-NOV-2010
entries
====================================================
id challengeid userid type code
1 1 1 1 -
2 2 1 1 -
3 6 1 1 -
4 6 1 2 -
The "type" in the entries table refers to if the entry type is either a non-regex based entry or regex based one. A user can submit both a regex and non-regex entry, therefore the above entry for challenge 6 is valid.
Example output
This is the style output of the query I would like (in this case the badge should be awarded):
(for userid 1)
Challenge 1 --> Joined in
Challenge 2 --> Joined in
Challenge 3 --> NULL
Challenge 4 --> NULL
Challenge 5 --> NULL
Challenge 6 --> Joined in
How?
Here are my questions
Whats the best way to do this in a query?
Is there a function I can use in MySQL to SELECT this range without resorting to some PHP?
The query so far
I'm doing a LEFT OUTER JOIN to join the challenge table and entries table (LEFT OUTER to make sure to preserve the challenges the user has not joined in), then sort by challenge start_date to see if the user has not joined in for 3 or more consecutive challenges.
SELECT challenge.id AS challenge_id, entries.id AS entry_id
FROM challenge_entries entries
LEFT OUTER JOIN challenge_details challenge
ON entries.challengeid = challenge.id
WHERE entries.userid = <user_id>
ORDER BY challenge.start_date
GROUP BY entries.challengeid
important edit: for this badge to make sense the criteria will need to be 3 or more consecutive challenges sandwiched between challenges that were joined in i.e. like the example output above. Otherwise anyone who joins in a challenge for the first time will automatically receive the badge. The user has to be seen to have been "away" from participating in challenges for a while (>=3)
I think you need to use the other table to start from...
SELECT challenge.id AS challenge_id,
entries.id AS entry_id
FROM
challenge_details challenge
LEFT JOIN challenge_entries entries ON entries.challengeid = challenge.id and entries.userid = <user_id>
ORDER BY challenge.start_date
adding a group by can be done as you want...

Categories