I need to select from the table competition_rounds the latest added records which are linked to the competition_seasons table with the season_id column, eg:
competition_rounds
id | name | season_id
1 Round A 20
2 Round B 20
3 Round A 21
4 Round B 21
competition_seasons
id | name | competition_id
20 2017/2018 40
21 2018/2019 40
I want return only:
round_id | round_name | season_id | season_name
3 Round A 21 2018/2019
4 Round B 21 2018/2019
the problem's that my query return all rounds available:
$sql = $this->db->prepare("SELECT max(r.id) AS round_id,
r.name as round_name, r.season_id AS season_id, s.name AS season_name
FROM competition_rounds r
JOIN competition_seasons s ON r.season_id = s.id
JOIN competition c ON s.competition_id = c.id
WHERE c.id = :competition_id
GROUP BY r.id
ORDER BY max(r.season_id) DESC");
$sql->bindParam("competition_id", 40);
$sql->execute();
$rounds = $sql->fetchAll();
return $response->withJson($rounds);
NB: The table competition simply contains a list of competition references.
If I understand correctly, you can use a subquery to return only the latest season from the seasons table:
SELECT r.id AS round_id,
r.name as round_name, r.season_id AS season_id, s.name AS season_name
FROM competition_rounds r JOIN
(SELECT s.*
FROM competition_seasons s
WHERE s.competition_id = :competition_id
ORDER BY s.id DESC
LIMIT 1
) s
ON r.season_id = s.id ;
Your question only mentions two tables, although the query has three. This is only based on the question.
You has no any competition columns in SELECT so you can just omit it from the query.
Take the last added (max(id)) season for a given :competition_id
SELECT r.id AS round_id,
r.name as round_name, r.season_id AS season_id, s.name AS season_name
FROM competition_rounds r
JOIN competition_seasons s ON r.season_id = s.id
WHERE s.id = (SELECT max(cs.id)
FROM competition_seasons cs
WHERE cs.competition_id = :competition_id)
Related
Table 1
----------
NameID Name
------------------
1 A
2 B
3 C
-----------------
Table 2
--------------------
ID NameID Order
--------------------
1 1 Sugar
2 1 Salt
3 2 Garlic
4 2 Sugar
5 2 Onion
6 3 Oil
7 3 Black pepper
I want to return only the latest and only one record per nameID from
right table I dont know what code to use
This is the Result I want to return
RESULT
----------------------------
Name Order
---------------------------
A Salt
B Onion
C Black pepper
Controller.php
return DB::table('table1')
->leftjoin('table2','table1.nameID','=','table2.nameID')
-get();
try this
$data = Table1::select('Table1.Name', 'Table2.Order','Table2.ID')
->leftJoin('Table2', function($query) {
$query->on('Table1.NameID','=','Table2.NameID')
->whereRaw('Table2.ID IN (select MAX(a2.ID) from Table2 as a2 join Table1 as u2 on u2.NameID = a2.NameID group by u2.NameID)');
})->get();
Edited :
$data = Table1::select('Table1.Name', 'Table2.Order','Table2.ID')
Use not exists to filter
select Name, Order
from Table1 a
inner join
(
Select a.NameID, Order from Table2 a
where not exists(select 1 from Table2 b where a.NameID = b.NameID and a.ID < b.ID)
)b on a.NameID = b.NameID
You can try this below script-
SELECT B.NameID, B.Name, C.[Order]
FROM
(
SELECT Nameid,MAX(ID) ID
FROM table_2
GROUP BY NameID
)A
INNER JOIN Table_1 B ON A.NameID = B.NameID
INNER JOIN Table_2 C ON A.NameID = C.NameID AND A.ID = C.ID
Table mpkids_students AS A
id BranchId Email Mobile StudentId
9497 25 mpsuraj2016#gmail.com 8700698773 25
9498 25 m016#gmail.com 8700698776 26
Table mpkids_student_image_gallery AS B
id like_count student_id
1 25 27
Table mpkids_visitors AS C
id student_id
1 9497
2 9497
3 9497
Table mpkids_visitors_count AS D
id visitor_count student_id
1 4 23
Table mpkids_image_likes AS E
id student_id
1 67
Table mpkids_relatives_data AS F
id student_id rel_email rel_mobile
1 9497 kushwahji#gmail.com 9009859691
2 9497 kushwah#gmail.com 7566403326
3 9497 kushwah#gmail.com 1236403326
4 9497 suraj#gmail.com 123640332
Table mpkids_paidstatus AS G
id student_id Received
1 9497 7500
2 9497 3000
3 9497 3000
MYSQL QUERY
SELECT A.id as student_id,
COUNT(DISTINCT B.id) as images,
COUNT(DISTINCT C.id)+ COUNT(DISTINCT D.visitor_count) as visits,
count(DISTINCT E.id) + SUM(B.like_count) as likes,
COUNT(DISTINCT A.Email)+COUNT(DISTINCT F.rel_email) as emails,
COUNT(DISTINCT A.Mobile)+COUNT(DISTINCT F.rel_mobile) as moibles,
SUM(G.Received) as Received
FROM mpkids_students AS A
LEFT JOIN mpkids_student_image_gallery AS B ON B.student_id = A.id
LEFT JOIN mpkids_visitors AS C ON C.student_id = A.id
LEFT JOIN mpkids_visitors_count AS D ON D.student_id = A.id
LEFT JOIN mpkids_image_likes AS E ON E.student_id = A.id
LEFT JOIN mpkids_relatives_data AS F ON F.student_id = A.id
LEFT JOIN mpkids_paidstatus AS G ON G.student_id = A.id
WHERE A.BranchId = 25
GROUP BY A.id
ORDER BY A.StudentId DESC
Result:
student_id images visits likes emails moibles Received
9497 0 3 NULL 4 5 202500
9498 0 0 NULL 1 1 NULL
Problem Explanation:
Received Field returning wrong value i have tried many queries but not getting solution
Received Field correct value 13500 for student_id = 9497
Please help me to find solution.
You are getting wrong output because, when you are joining based on studentid, you are getting multiple records from mpkids_paidstatus table for each student, which is adding up and returning a wrong output.
You can also write your query like following using subquery.
SELECT A.id as student_id,
COUNT(DISTINCT B.id) as images,
COUNT(DISTINCT C.id)+ COUNT(DISTINCT D.visitor_count) as visits,
count(DISTINCT E.id) + SUM(B.like_count) as likes,
COUNT(DISTINCT A.Email)+COUNT(DISTINCT F.rel_email) as emails,
COUNT(DISTINCT A.Mobile)+COUNT(DISTINCT F.rel_mobile) as moibles,
(select SUM(Received) from mpkids_paidstatus ps where ps.student_id=a.id) as Received
FROM mpkids_students AS A
LEFT JOIN mpkids_student_image_gallery AS B ON B.student_id = A.id
LEFT JOIN mpkids_visitors AS C ON C.student_id = A.id
LEFT JOIN mpkids_visitors_count AS D ON D.student_id = A.id
LEFT JOIN mpkids_image_likes AS E ON E.student_id = A.id
LEFT JOIN mpkids_relatives_data AS F ON F.student_id = A.id
WHERE A.BranchId = 25
GROUP BY A.id
ORDER BY A.StudentId DESC
I have a simple multiple school management system and I am trying to get total number of teachers, and total number of students for a specific school. My table structures are as follows:
teachers
--------------------------
id | schoolid | Name | etc...
--------------------------
1 | 1 | Bob |
2 | 1 | Sarah|
3 | 2 | John |
students
--------------------------
id | schoolid | Name | etc...
--------------------------
1 | 1 | Jack |
2 | 1 | David|
3 | 2 | Adam |
schools
--------------------------
id | Name | etc...
---------------------------
1 | River Park High |
2 | Stirling High |
I can count just all teachers with the following query:
SELECT COUNT(a.id) AS `totalteachers`
FROM teachers a
LEFT JOIN schools b ON a.schoolid = b.id WHERE b.id = '1'
and similarly I can count the number of teachers with the following query:
SELECT COUNT(a.id) AS `totalstudents`
FROM students a
LEFT JOIN schools b ON a.schoolid = b.id WHERE b.id = '1'
I am however struggling with trying to combine these two queries to get a simple result like this:
totalstudents | totalteachers
--------------------------------
2 | 2
I have tried the following:
SELECT COUNT(a.id) as `totalteachers`, COUNT(c.id) as `totalstudents`
FROM teachers a
LEFT JOIN schools b ON a.schoolid = b.id
LEFT JOIN students c ON c.schoolid=b.id WHERE b.id = '5'
You can do something like this
SELECT
id, name, s.total AS totalstudents, t.total AS totalteachers
FROM schools
JOIN (SELECT schoolid, COUNT(id) AS total FROM teachers GROUP BY schoolid)
AS t ON t.schoolid = id
JOIN (SELECT schoolid, COUNT(id) AS total FROM students GROUP BY schoolid)
AS s ON s.schoolid = id
then you can add where id = 2 or whatever to limit the school.
The problem with the multiple left joins is it generates additional records for each teacher to each student; artifically inflating your counts
There's four ways to solve this: (best imo is what Andrew bone did)
Simply select inline without the joins so the counts are not inflated. (most desirable in my mind as it's easy to maintain)
SELECT (SELECT COUNT(a.id) AS `totalteachers`
FROM teachers a
WHERE A.SchoolID = '1') as TotalTeachers
, (SELECT COUNT(a.id) AS `totalstudents`
FROM students a
WHERE a.SchoolID = '1') as TotalStudents
Use subqueries to get the counts first before the joins, then join. Since count will always be 1 a cross join works.
SELECT totalTeachers, totalStudents
FROM (SELECT COUNT(a.id) AS `totalteachers`
FROM teachers a
LEFT JOIN schools b
ON a.schoolid = b.id
WHERE b.id = '1')
CROSS JOIN (SELECT COUNT(a.id) AS `totalstudents`
FROM students a
LEFT JOIN schools b ON a.schoolid = b.id
WHERE b.id = '1')
Use key word distinct within the count so as not to replicate the counts and negate the artificial inflation (least desirable in my mind as this hides the artifical count increase)
SELECT COUNT(distinct a.id) as `totalteachers`, COUNT(distinct c.id) as `totalstudents`
FROM teachers a
LEFT JOIN schools b ON a.schoolid = b.id
LEFT JOIN students c ON c.schoolid=b.id WHERE b.id = '5'
Another way would be to use a window functions, however these are not available in mySQL.
SELECT COUNT(t.id) AS TotalTeachers, COUNT(st.id) AS TotalStudents
FROM schools s
INNER JOIN teachers t
ON s.id = t.schoolid
INNER JOIN students st
ON s.id = st.schoolid
Try this SQL. I havn't try it but it should work.
Hi I would like to compute and display the time spent between the datetime column from current row to the next row.
current table:
task_id | task | date | user_id
1 | Task 1 | 2017-04-30 08:30:23 | 35
2 | Task 2 | 2017-04-30 09:30:23 | 35
3 | Task 3 | 2017-04-30 10:00:23 | 35
expected results:
task_id | task | date | timespent
1 | Task 1 | 2017-04-30 08:30:23 | 60
2 | Task 2 | 2017-04-30 09:30:23 | 30
3 | Task 3 | 2017-04-30 10:00:23 | (compute it by current time)
I have a query like this but it seems it cannot get my expected results
SELECT A.task_id, A.date,A.task,A.user_id,
TIMESTAMPDIFF(MINUTE,A.date,B.date) AS timespent
FROM tbl_task A CROSS JOIN tbl_task B
WHERE B.task_id IN (SELECT MIN(C.task_id)
FROM tbl_task C
WHERE C.task_id > A.task_id)
AND A.user_id = 35
AND Month(A.date) = 5
ORDER BY A.task_id ASC
The issue of above query is it cannot get the last row or if the row is just one record. I would like to compute the last record or single record timespent by the current time now();
Any idea? Thanks for the help.
To keep the last row you should use a LEFT JOIN. The condition for the B.task_id should be in the ON clause. And you can use COALESCE(B.date, NOW()) to replace NULL with the current timestamp.
SELECT A.task_id, A.date,A.task,A.user_id,
TIMESTAMPDIFF(MINUTE,A.date, COALESCE(B.date, NOW())) AS timespent
FROM tbl_task A
LEFT JOIN tbl_task B ON B.task_id = (
SELECT MIN(C.task_id)
FROM tbl_task C
WHERE C.user_id = A.user_id
AND C.task_id > A.task_id)
WHERE A.user_id = 35
AND Month(A.date) = 5
ORDER BY A.task_id ASC
Note that I also added C.user_id = A.user_id to the WHERE clause of the subquery. Otherwise you might get a task_id of another user.
Since you only need the date from the next row, you can avoid the subquery using GROUP BY:
SELECT A.*,
TIMESTAMPDIFF(MINUTE,A.date, COALESCE(MIN(B.date), NOW())) AS timespent
FROM tbl_task A
LEFT JOIN tbl_task B
ON B.user_id = A.user_id
AND B.task_id > A.task_id
WHERE A.user_id = 35
AND Month(A.date) = 5
GROUP BY A.task_id
ORDER BY A.task_id ASC;
Demo: http://rextester.com/SDWX89625
Use an outer join. And if B.date is NULL, use NOW() instead.
Something like this:
SELECT A.task_id
, A.date
, A.task
, A.user_id
, TIMESTAMPDIFF(MINUTE,A.date,IFNULL(B.date,NOW()) AS timespent
-- ^^^^^^^ ^^^^^^^
FROM tbl_task A
LEFT
-- ^^^^
JOIN tbl_task B
ON B.task_id IN
-- ^^
( SELECT MIN(C.task_id)
FROM tbl_task C
WHERE C.task_id > A.task_id
)
AND A.user_id = 35
AND MONTH(A.date) = 5
ORDER BY A.task_id
This should work:
SELECT
a.task_id,
a.date,
a.task,
a.user_id,
TIMESTAMPDIFF(MINUTE,a.date,IF(b.date IS NULL,CURRDATE(),b.date) AS timespent
FROM tbl_task a
LEFT JOIN tbl_task b
ON a.task_id > b.task_id
WHERE a.user_id = 35
AND month(a.date) = 5
GROUP BY a.task_id
ORDER BY a.task_id
Basically, by using a left join, records without a match will have null values for their columns. The timespent column tests for a null, and uses the curr_date() instead.
I am working on developing sports site.
In this site I've two tables one is tbl_team which stores the team details and another table is tbl_tournamentmatches which stores the details of different rounds of tournament matches.
In my tbl_tournamentmatches I'm storing team1_id, team2_id, team1_score and team2_score.
My Table having entry like this:
tbl_tournamentmatches
match_id team1_id team2_id team1_score team2_score
5 4 9 15 5
6 9 16 15 5
7 4 16 5 15
8 4 16 5 15
tbl_team
team_id team_title
4 KKR
9 RR
16 CSK
I want Result Should look like this:-
Team name Score
CSK 35
KKR 25
RR 20
I'd used this query :-
select * from
(
SELECT sum(team1_points) as totalpoints,t.team_title
from tbl_team t
left join tbl_tournamentmatches m
on t.team_id = m.team1_id
where tournament_id = 3 AND agegroup_id = 36
group by team1_id
union
SELECT sum(team2_points) as totalpoints,t.team_title
from tbl_team t
left join tbl_tournamentmatches m
on t.team_id = m.team2_id
where tournament_id = 3 AND agegroup_id = 36
group by team2_id
) s
But i got result like this :-
KKR 25
RR 15
RR 5
CSK 35
Any Help will be appreciated. Thanks in advance.
Do the joins to get the team and points for each match, and then do the sum on the results of that:-
SELECT team_title, sum(team_points) as totalpoints
FROM
(
SELECT team1_id AS team_id, team1_points AS team_points, t.team_title
FROM tbl_team t
LEFT JOIN tbl_tournamentmatches m
ON t.team_id = m.team1_id
WHERE tournament_id = 3 AND agegroup_id = 36
UNION ALL
SELECT team2_id AS team_id, team2_points AS team_points, t.team_title
FROM tbl_team t
LEFT JOIN tbl_tournamentmatches m
ON t.team_id = m.team2_id
WHERE tournament_id = 3 AND agegroup_id = 36
) s
GROUP BY team_id, team_title
try this query
SELECT t.team_name
,SUM(CASE
WHEN t.team_id = tn.team1_id THEN tn.team1_score
WHEN t.team_id = tn.team2_id THEN tn.team2_score
END) AS score
FROM team t
LEFT JOIN tournament tn ON t.team_id = tn.team1_id OR t.team_id = team2_id
GROUP BY t.team_name
You almost got it.
In your query I see fields that you don't include in your table (e.g. agegroup_id), but you only are a step of a solution: change your outter "select * from " for a: "select sum(totalpoints), team_title" and add a group by at the end: "group by team_title"
select sum(totalpoints) as totalpoints, team_title from
(
SELECT sum(team1_score) as totalpoints, t.team_title
from tbl_team t
join tbl_tournamentmatches m
on t.team_id = m.team1_id
--where tournament_id = 3 AND agegroup_id = 36
group by team1_id
union
SELECT sum(team2_score) as totalpoints, t.team_title
from tbl_team t
join tbl_tournamentmatches m
on t.team_id = m.team2_id
--where tournament_id = 3 AND agegroup_id = 36
group by team2_id
) s
group by team_title;
Use Union all to make all team and score as different rows.
Then use an Inner Join.
Query
select t2.team_title as TeamName,
sum(team_score) as Score
from
(
select match_id,team1_id as team_id, team1_score as team_score
from tblMatch
union all
select match_id,team2_id as team_id, team2_score as team_score
from tblMatch
)t1
join tblTeam t2
on t1.team_id = t2.team_id
group by t2.team_id;
SQL Fiddle