is it possible to do subquery inside GROUP BY? - php

my problem analogy is like this:
table: place
id title branch
===============================
1 pizza store california
2 pizza store manhattan
3 coffee shop california
4 pizza store texas
5 cookie store new york
table: rating
id place_id rating
================================
1 1 3.5
2 2 5.0
3 2 4.2
4 2 5.0
5 5 4.0
i use query:
SELECT F.id AS id, F.title AS title, G.rating
FROM place F
JOIN rating G ON F.id = G.place_id
GROUP BY F.title
the display will be :
id title rating
===========================
1 pizza store 3.5
3 coffee shop -
5 cookie store 4.0
what i want is to sort title that has rating with the maximum one, in this case i want it to display pizza store with rating 5 and id 2. Is it possible to insert some subquery inside GROUP BY ?
Thanks in advance!!

try
SELECT F.id , F.title, s.Maxrating
FROM place F
INNER JOIN (SELECT id,Max(rating) as MaxRating FROM rating GROUP BY place_id ) s
ON s.id = F.id

SELECT F.id AS id, F.title AS title, max(G.rating)
FROM place F, rating G
where F.id = G.place_id(+)
group by f.id, f.title

Related

left join and return only the latest record from right table using LARAVEL 6.5.0

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

Get Highest Sal rows according to empid wise in Mysql

I have 3 tables
Employee
---------------
ID Name
1 John
2 Kelly
3 Leo
Dept
-------
ID Name
1 Finance
2 A/c
3 Marketing
Accout
--------------------
Id EmpId Dept Sal
1 1 1 25,000
2 1 2 30,000
3 2 2 20,000
4 2 1 15,000
5 3 3 20,000
Now i need to get highest salary row with appropriate data.
Like for Emp id 1 highest sal = 30,0000 so get whole row id = 2 from a/c table
Emp id 2 highest sal = 20,000 so get whole row id = 3 from a/c table
I try with
SELECT E.id,E.name AS emp_name,D.name AS dept_name,
A.Dept as dept_id,max(A.sal) AS max_sal
FROM Accout A
JOIN Employee E ON A.EmpId = E.ID
JOIN Dept D ON A.Dept = D.Id
Group by EmpId
So i got result like
Id emp_name dept_name dept_id max_sal
1 John Finance 1 30,000
2 Kelly A/c 2 20,000
3 Leo Marketing 3 20,000
But i need result like this
Id emp_name dept_name dept_id max_sal
1 John A/c 2 30,000
2 Kelly A/c 2 20,000
3 Leo Marketing 3 20,000
Please let me know how it's possible so i can got the correct output.
Thanks in Advance.
You need to find the max salary row first and then join with other tables.
This query should work for you.
SELECT
E.id, E.name AS emp_name, D.name AS dept_name, A.Dept AS dept_id, max_sal
FROM
Accout A
JOIN
(SELECT
EmpId, MAX(sal) AS max_sal FROM
Accout GROUP BY EmpId
) B ON A.EmpId = B.EmpId AND A.sal = B.max_sal
JOIN Employee E ON A.EmpId = E.ID
JOIN Dept D ON A.Dept = D.Id;
Instead of using GROUP BY, I used ORDER BY since you said you just want the highest to lowest salary, plus I removed max():
SELECT E.id
E.name AS emp_name,
D.name AS dept_name,
A.DeptId as dept_id,
A.sal AS max_sal
FROM Account A
JOIN Employee E ON A.EmpId = E.ID
JOIN Dept D ON A.DeptId = D.Id
ORDER BY max_sal DESC
LIMIT 3
You can use LIMIT if you want to limit the returned rows

Select rows from a table where id in another second table based on second table ids shows results top as well as next results as it is + Mysql

I have users table
users
id name
1 test1
2 test2
3 test3
4 test4
5 test5
6 test6
7 test7
8 test8
9 test9
10 test10
Payment
id userid name
1 5 test5
2 3 test3
3 9 test9
i want results like this
id name
3 test3
5 test5
9 test9
1 test1
2 test2
4 test4
6 test6
7 test7
8 test8
10 test10
i want whoever pays the amount that one should be display in top order by.
SELECT u.`id` id, u.`name` NAME
FROM users u
INNER JOIN payment p
ON u.id=p.userid
UNION
SELECT u.`id` id, u.`name` NAME
FROM users u
This will produce your desired results:
SELECT a.id, a.name, 1 AS RN
FROM users a
INNER join payments b
ON a.id=b.userid
UNION ALL
SELECT a.id, a.name, 2 AS RN
FROM users a
LEFT JOIN payments b
ON a.id=b.userid
WHERE b.id IS NULL
ORDER BY RN, a.id
The first query simply selects the id and name columns for rows that appear in the payments table.
The second query gets the id and name columns for rows that do not appear in the payments table.
The UNION ALL simply merges the results together.
Notice the 1 AS RN and the 2 AS RN that are in the queries. This is an extra column that I have added so that the results can be ordered how you wanted. You can simply ignore this when you process the data.
You can do this with LEFT JOIN and ORDER BY:
SELECT
user.id, user.name
FROM
user
LEFT JOIN
payment ON user.id = payment.userid
ORDER BY payment.id DESC, user.id
This would fulfill your requirement, "i want whoever pays the amount that one should be display in top order by". But if you want the results as shown in the results you have given:
SELECT
user.id, user.name
FROM
user
LEFT JOIN
payment ON user.id = payment.userid
ORDER BY CASE
WHEN payment.id IS NULL THEN 1
ELSE 0
END , payment.id , user.id

Getting count from inner join table

I have tables as described below:
subscription_plans (Table for storing all plans)
id plan days_limit added_on status rate
------------------------------------------------
1 PlanA 15 1398249706 1 150.00
2 PlanB 15 1398249706 1 150.00
subscribed_videos (Table for storing details of video in each plans)
id plan_id videoid
----------------------
1 1 1
2 2 2
subscription_groups (Table for storing groups where a plan can be part of another plan. ie, Plan A be a plan with 2 other individual plans, Plan B and C )
id plan_id assosiated_plan_id added_on
----------------------------------------------
1 1 2 1398249706
usersubscription (Table for storing user subscribed plans)
id user_id plan_id subscribed_on
---------------------------------------
1 1 1 1398771106
Now, my problem is that how can I get the count of videos for each plans. If Plan A contains both Plan B and C (subscription_groups table), then the count should return the total video count for each individual plans in that particular plan. Now I have done with a query which will return plan details along with count of videos for a plan but I am not able to join it with subscription_groups. How can I accomplish this in a single query.
$data['planquery']=$this->db->query("select
us.plan_id,us.subscribed_on,sp.plan,sp.days_limit,sp.rate,count(sv.videoid) from
usersubscription as us INNER JOIN
subscription_plans as sp ON us.plan_id=sp.id INNER JOIN subscribed_videos as sv ON sp.id=sv.plan_id where sp.status=1 and us.user_id=1");
Expected Result:
plan_id subscribed_on plan days_limit rate count
-------------------------------------------------------
1 1398771106 PlanA 15 150.00 2
Can anyone help me to find a solution for this?
Thanks in advance.
You can do so
SELECT
us.plan_id,
us.subscribed_on,
sp.plan,
sp.days_limit,
sp.rate,
COUNT(sv.videoid)
FROM
usersubscription AS us
RIGHT JOIN subscription_plans AS sp
ON us.plan_id = sp.id
INNER JOIN subscribed_videos AS sv
ON sp.id = sv.plan_id
INNER JOIN subscription_groups g
ON(g.plan_id =sv .plan_id OR sv.plan_id= g.assosiated_plan_id)
WHERE sp.status = 1
AND (us.user_id = 1 OR us.user_id IS NULL )
Demo
Since user has only plan associated but the associated plan can also has another plan linked so the last condition will check the user id but for is null to for the second linked plan user id will be null due to right join on subscription_plans
Edit
SELECT
u.plan_id,
u.subscribed_on,
p.plan,
p.days_limit,
p.rate
,COUNT(DISTINCT v.`videoid`)
FROM `usersubscription` u
JOIN `subscription_groups` g
ON (u.`plan_id` = g.`plan_id`)
RIGHT JOIN `subscription_plans` p
ON(u.`plan_id` = p.`id` OR g.`assosiated_plan_id` = p.`id`)
INNER JOIN `subscribed_videos` v ON(v.`plan_id`=g.`assosiated_plan_id` OR u.`plan_id`= v.`plan_id`)
WHERE u.`id`=1 AND p.`status` = 1
Demo 1 Demo2
For video ids you can use group_concat
SELECT
u.plan_id,
u.subscribed_on,
p.plan,
p.days_limit,
p.rate
,COUNT(DISTINCT v.`videoid`) `video_count` ,
GROUP_CONCAT(DISTINCT v.`videoid`) `video_ids`
FROM `usersubscription` u
JOIN `subscription_groups` g
ON (u.`plan_id` = g.`plan_id`)
RIGHT JOIN `subscription_plans` p
ON(u.`plan_id` = p.`id` OR g.`assosiated_plan_id` = p.`id`)
INNER JOIN `subscribed_videos` v ON(v.`plan_id`=g.`assosiated_plan_id` OR u.`plan_id`= v.`plan_id`)
WHERE u.`id`=1 AND p.`status` = 1
Demo 1a Demo 2a

SQL/ PHP Joining table, ignoring multiple records

I don't really know how to even search for resolution of this problem, didn't find anything specific, so here goes...
I have four tables, let's simplify them:
players
=======
id name surname
1 John Arbuckle
2 Walter White
3 Don Draper
4 Louis CK
5 Tyrion Lannister
6 Abed Nadir
sports
======
id sport
1 football
2 handball
positions
=========
id name sport_id
1 goalie 1
2 defense 1
3 attack 1
4 goalie 2
5 pivot 2
6 wing 2
7 center 2
player_position
===============
player_id position_id
1 1
1 2
1 5
2 7
2 5
3 2
4 2
5 1
5 3
6 7
6 5
So, player can play multiple sports and on multiple positions. First, I have to display list of players for a certain sport, including a column with positions they play.
What I started with is JOIN statement where I'd join those tables and have multiple rows for each player ID. That's close, but not very correct. And what I need to get is a tables like this:
FOOTBALL
ID name surname position
1 John Arbuckle PHP array(goalie,defense)
HANDBALL
ID name surname position
1 John Arbuckle PHP array(pivot)
EDIT:
So what I was looking for was GROUP_CONCAT().
Thanks guys!
select p.id, p.name, p.surname, group_concat(po.name)
from players p
inner join player_position pp on pp.player_id = p.id
inner join positions po on po.id = pp.position_id
inner join sports s on s.id = po.sport_id
where s.sport = 'football'
group by p.id
See this SQLFiddle example
For football:
SELECT players.name, players.surname, positions.name
FROM players, sports, positions, player_position
WHERE sports.id = 1 AND positions.sport_id = sports.id AND payer_position.position_id = positions.id AND players.id = player_position.player_id;
For Handball:
SELECT players.name, players.surname, positions.name
FROM players, sports, positions, player_position
WHERE sports.id = 2 AND positions.sport_id = sports.id AND payer_position.position_id = positions.id AND players.id = player_position.player_id;
I'm not sure if this is foolproof (not tested) but…
SELECT pp.`player_id` AS 'ID',s.`id` AS 'sport_id',s.`sport`,ps.`name` AS 'position',pl.`name`,pl.`surname` FROM `sports` s
INNER JOIN `positions` ps ON s.`id`=ps.`sport_id`
INNER JOIN `player_position` pp ON pp.`position_id`=ps.`id`
INNER JOIN `players` pl ON pl.`id`=pp.`player_id`
ORDER BY s.`id`,pp.`player_id`,ps.`id`
Here's a more detailed version:
SELECT
s.`id` AS 'sport_id',s.`sport`,
ps.`id` AS 'position_id',ps.`name` AS 'position',
pl.`id` AS 'player_id',pl.`name`,pl.`surname`
FROM `sports` s
INNER JOIN `positions` ps ON s.`id`=ps.`sport_id`
INNER JOIN `player_position` pp ON pp.`position_id`=ps.`id`
INNER JOIN `players` pl ON pl.`id`=pp.`player_id`
ORDER BY s.`id`,pp.`player_id`,ps.`id`

Categories