I have a table like this
id userid game date_t hdigit inside outside
1 user101 xy 02-09-2017 1 10
2 user101 xy 02-09-2017 1 40
3 user101 xx 02-09-2017 2 40
4 user101 xx 02-09-2017 3 90
I want display data like
id userid game date_t hdigit inside outside
1 user101 xy 02-09-2017 1 10 40
3 user101 xx 02-09-2017 2 40
4 user101 xx 02-09-2017 3 90
I have tried this
SELECT h.userid,h.game,h.date_t,h.hdigit,h.inside,htwo.outside
FROM `hadap_game` AS h JOIN hadap_game AS htwo WHERE h.userid=:user
AND htwo.userid=:uer AND h.hdigit=htwo.hdigit AND h.game=htwo.game
AND h.inside IS NOT NULL AND htwo.outside IS NOT NULL
it is printing the above thing but I want to print the row which have null values too
I think you could probably do this simply using GROUP BY?
SELECT
h.userid,
h.game,
h.date_t,
h.hdigit,
MAX(IFNULL(h.inside, htwo.inside)) AS inside,
MAX(IFNULL(h.outside, htwo.outside)) AS outside
FROM
hadap_game AS h
LEFT JOIN hadap_game AS htwo ON htwo.userid = h.userid AND htwo.hdigit = h.hdigit AND htwo.game = h.game AND htwo.id <> h.id
WHERE
h.userid = :user
GROUP BY
h.userid,
h.game,
h.date_t,
h.hdigit;
This does a few other things that you might not need/ want, but it's basically the same as your original query, other than it works when there aren't two rows per unique reference.
Assuming that there will only ever be 1 or 2 rows (so not 3 or more matching rows):-
SELECT h.userid,
h.game,
h.date_t,
h.hdigit,
COALESCE(h.inside,h2.inside) AS inside,
COALESCE(h.outside,h2.outside) AS outside
FROM `hadap_game` AS h
LEFT OUTER JOIN hadap_game AS h2
ON h.hdigit=h2.hdigit
AND h.game=h2.game
WHERE h.userid=:user
AND h2.userid=:uer
UNION
SELECT h2.userid,
h2.game,
h2.date_t,
h2.hdigit,
COALESCE(h.inside,h2.inside) AS inside,
COALESCE(h.outside,h2.outside) AS outside
FROM `hadap_game` AS h2
LEFT OUTER JOIN hadap_game AS h
ON h.hdigit=h2.hdigit
AND h.game=h2.game
WHERE h.userid=:user2
AND h2.userid=:uer2
Related
Hi We have 3 Table of a music which is something like this in MySql :
1st Table :
the first table is for playlist table where music playlist is exist.
playlistId playlistTitle categoryId
1 hello 0
2 wow 0
3 wi-fi 0
4 awesome 0
5 sixer 1
6 four 1
7 boundary 2
2nd Table :
2nd table is for songRelation table where every playlist is associated with thier song
playlistId songId
1 4
1 3
1 43
1 57
1 98
2 56
2 67
2 90
2 78
3 98
3 78
3 89
43 90
3rd Table : the 3rd table is for song table where song detail exist
songId songTitle
4 hello
3 real hero
43 singalone
57 awesom
98 really
78 sakaka
98 shikwa
89 moha
90 hello2
67 Sneh
actually i am fetching the result something like this:
playlistId songId categoryId songTitle
1 4 0 hello
1 3 0 real hero
2 56 0 singalone
2 67 0 Sneh
3 78 0 sakaka
3 98 0 Shikwa
where the every playlistId will be with their first 2songIdand with theircategoryIdand also withsongTitle`.
but i want to count the total song with every playlistId
after getting the total song result i want will be something like this :
playlistId songId categoryId songTitle totalSong
1 4 0 hello 5
1 3 0 real hero 5
2 56 0 singalone 4
2 67 0 Sneh 4
3 78 0 sakaka 3
3 98 0 Shikwa 3
here is the jsfiddle Demo where query is without totalSong http://sqlfiddle.com/#!9/7eda7/5
What subquery will be added to get the above desired result.
To get exactly the result you asked, use this:
select p.playlistId,
s.songId,
p.categoryId,
s.songTitle,
(select count(*) from songRelation where playlistId = p.playlistId) totalSong
from playlist p
inner join songRelation r on p.playlistId = r.playlistId
inner join song s on r.songId = s.songId
Using a group by on the main query would merge the detailed song data, forcing you to run two queries: one for details (first 4 fields) and a second query, to recover the totals (last column). Using this solution, you get all detailed data and totals, the sub-query will recover the count of songs for each playlist, the way you asked.
UPDATE:
This way, suggested by rlanvin, should make the query faster, because instead on computing the subquery for each row, it gets computed only once, and then is joined to the main query. The result is the same:
select p.playlistId,
s.songId,
p.categoryId,
s.songTitle,
r1.totalSong
from playlist p
inner join songRelation r on p.playlistId = r.playlistId
inner join song s on r.songId = s.songId
inner join (SELECT playlistid, COUNT(songId) as totalSong from songRelation group by playlistid) r1 on p.playlistId = r1.playlistId
I have added this query to ur SQLFIDDLE.
SELECT p.playlistId, s.songId, p.categoryId, s.songTitle,
(select count(sr1.songId) from songRelation sr1
where sr1.playlistid=p.playlistid
group by sr1.playlistId) as total,
#r := IF (#pid = p.playlistId,
IF (#pid := p.playlistId, #r+1, #r+1),
IF (#pid := p.playlistId, 1, 1)) AS rn
FROM playlist AS p
CROSS JOIN (SELECT #r:=0, #pid:=0) AS vars
INNER JOIN songRelation AS sr ON p.playlistId = sr.playlistId
INNER JOIN song AS s ON sr.songid = s.songid
ORDER BY p.playlistId, s.songId ) AS t
WHERE t.rn <= 2
It is giving the required output. Check the Demo Here
Using Group Functions you can do this:
SELECT `playlistid`, COUNT(`songid`)
FROM `playlist`
GROUP BY `playlistid`
I'm trying to find a patient's appointments and messages count. My table records are like below 3 table patient, appointments and messages
Patient table
pid fname lname
1 john sid
2 rother ford
3 megan rough
4 louis kane
appointments table
id pid appointment_date
1 1 2015-08-04
2 2 2015-08-05
3 1 2015-08-06
4 1 2015-08-07
5 3 2015-08-07
6 2 2015-08-08
7 4 2015-08-13
8 1 2015-08-12
Messages table
id pid description message_date
1 2 join 2015-08-04
2 2 update 2015-08-05
3 3 join 2015-08-05
4 4 update 2015-08-10
5 3 test 2015-08-07
So if write query to find counts i'm getting wrong values
SELECT pd.fname,pd.lname , pd.pid, COUNT( a.id ) AS app_cnt, COUNT( m.id ) AS mes_cnt
FROM patient pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid
LEFT OUTER JOIN messages m ON m.pid = pd.pid
GROUP BY pd.pid
ORDER BY pd.pid
fname lname pid app_cnt mes_cnt
john sid 1 4 0
rother ford 2 4 4
megan rough 3 2 2
louis kane 4 1 1
Here pid 1 have 4 appointments and 0 messages, pid 2 have 2 appointments and 2 messages but getting wrong values.
Can someone please help to resolve this issue. I'm not interested in writing sub queries for this.
Functionality looks simple but I'm really facing problem for writing query.
Anymore suggestions please.
After thoroughly analysing your problem and tables, It cannot be done directly using simple query as LEFT OUTER JOIN is returning some superfluous records, that's why to filter it, you will have to use temporary table and modify the query as:
Select temp.fname, temp.lname, temp.pid, a_count, count(m.pid) as m_count from
(SELECT fname,lname,pd.pid, count(a.pid) as a_count
FROM patients pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid group by pd.pid) temp
LEFT OUTER JOIN messages m ON m.pid = temp.pid
group by temp.pid
Explanation:
It will join patients and appointments table and group them by pid so that messages from message table do not repeat for each patients.pid.
The wrong result is as a result of left outer join as it is giving wrong results for this query
SELECT *
FROM patients pd
LEFT OUTER JOIN appointments a ON a.pid = pd.pid
LEFT OUTER JOIN messages m ON m.pid = pd.pid
Since we need to limit the results of first two joins, hence temporary table is necessary.
Hi I have try to find a solution for a query to get the minvalues along with latest time stamp.
I have following tables
Table1
sno user_id name subject rank Timestamp
1 10 SS maths1 1 2014-12-05 17:24:33
2 10 SS maths2 2 2014-12-05 17:24:33
3 10 PH phy1 3 2014-12-05 17:24:33
4 10 PH phy2 4 2014-12-05 17:24:33
5 10 SS maths1 2 2014-12-04 17:24:33
6 10 SS maths2 1 2014-12-04 17:24:33
7 10 PH phy1 3 2014-12-04 17:24:33
8 10 PH phy2 4 2014-12-04 17:24:33
Tabe12
sno name Status
1 SS Active
2 PH ACtive
3 So Inactive
So I am trying to get the following result
sno userid name subject rank timpestamp
1 10 SS maths1 1 2014-12-05 17:24:33
2 10 PH phy1 3 2014-12-05 17:24:33
So far I tried this query I am able to get the latest time and least rank values for subjects with Distinct name.
but they are not connected to each other means I getting the latesttime stamp and least value from some other row. Please help me How to solve it.
SELECT DISTINCT(T1.`name`),
T1.`user_id`,
T1.`subject`,
MAX(T1.`Timestamp`) as latest_Timestamp,
MIN(T1.`rank `) as rank
FROM Table1 T1,Table2 T2
where T1.`user_id`='10'
AND T2.`status` = 'Active'
AND T1.`name` = T2.`name`
GROUP BY T1.`exercise_id`
ORDER BY T1.`quality_id`, T1.`Timestamp` ASC
Relational databases work well on sets. So think of the data in different sets
You need a set that combines t1 and t2
You need a subset of t1 that only consists of the min rank and max timestamp for each user_Id and name.
So T1 and T2 are joined generating the universe of data and columns you need. We then join to the subquery contianing the subset to filter out the non max timestamp and non-min rank you want.
SELECT T1values.name,
T1values.user_id,
T1values.subject,
T1values.rank,
T1values.timestamp
FROM Table2 T2
INNER JOIN table1 t1Values
ON t1values.sno = t2.sno
and t2.status='Active'
INNER JOIN (SELECT user_Id, name max(timestamp) maxTime, min(rank) Mrank
FROM Table1
GROUP BY user_Id, Name) T1
ON t1.name = T1values.name
and t1.user_Id = t1values.user_ID
and t1.maxTime = T1Values.timestamp
and t1.rank = T1values.mrank
WHERE T1values.user_id='10'
ORDER BY T1values.quality_id, T1values.Timestamp ASC
I have those 3 tables
candidates
cdid cdname
1 Moussa
2 Moustafa
3 Haitham
positions
posid posname
1 pos1
2 pos2
3 pos3
joboffers
cdid posid salary
1 1 600
1 2 800
1 3 700
2 1 500
2 2 700
2 3 900
3 2 1000
3 3 500
I need to make a query that get the cdname with max salary for every position
the table should be like this
cdname posname salary
moussa pos1 600
haitham pos2 1000
moustafa pos3 900
I am using this query but it's not getting the correct cdid
$sql="select joboffers.cdid,joboffers.posid,Max(joboffers.salary),candidates.cdname
FROM joboffers,candidates
Where joboffers.cdid=candidates.cdid
Group by joboffers.posid";
Try this :)
SELECT sub.cdname, sub.posname, sub.salary
FROM (
SELECT * FROM joboffers jo
INNER JOIN positions ps USING (posid)
INNER JOIN candidates cd USING (cdid)
ORDER BY posid, salary DESC
) sub
GROUP BY sub.posid
I think you need to group by all non-aggregated columns, like this:
SELECT j.cdid, c.cdname, j.posid, MAX(j.salary)
FROM joboffers j
JOIN candidates c ON j.cdid = c.cdid
GROUP BY j.cdid, c.cdname, j.posid
SELECT c.cdname, p.posname, MAX(j.salary)
FROM joboffers j
INNER JOIN candidates c ON j.cdid = c.cdid
INNER JOIN positions p ON j.posid = p.posid
GROUP BY c.cdname, p.posname
enter code hereSELECT customerNumber, MAX(amount)
FROM payments
GROUP BY customerNumber
ORDER BY MAX(amount);
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.