SQL Query with drop or null on statement - mysql

On a Userpage we show Awardpictures recived from 2 sql tables.
In zg15_auszeichnungen_vergeben which contains all user awards in form from award type id`s, award dates ... we read over the users pilotID the award datas.
Over a LEFT JOIN from zg15_auszeichnungen_main we get the Awardpicture and the Award Name which shows on the page.
SELECT v.pilotID, v.auszBereichID, v.auszTypID, v.gameID, v.auszDatum, m.mainGrafik, m.mainName
FROM zg15_auszeichnungen_vergeben
LEFT JOIN zg15_auszeichnungen_main m ON v.auszMainID = m.mainID
WHERE v.pilotID = '$pilotID'
AND v.auszBereichID = 6
AND v.auszTypID = 100
AND v.gameID = 1
ORDER BY v.auszDatum;
Because there are to many year awards(1 year,2years,3years...12 years) together wit some other awards, i want just show the oldest award of the years (just 12 years instead of all). The year awards have the value 11 from m.mainKatID and the oldest has the highest value from m.mainPunkte.
Other awards like (most Postpoints) have other values (10) in mainKatID.
I'm not familiar with mysql and don't get the result i want.

Change your ORDER BY to ORDER BY m.mainKatID DESC LIMIT 3 and set limit to return 3 records.
SELECT
v.pilotID, v.auszBereichID, v.auszTypID, v.gameID, v.auszDatum,
m.mainGrafik, m.mainName FROM zg15_auszeichnungen_vergeben v
LEFT JOIN zg15_auszeichnungen_main m ON v.auszMainID = m.mainID
WHERE v.pilotID = '$pilotID'
AND v.auszBereichID = 6
AND v.auszTypID = 100
AND v.gameID = 1
ORDER BY m.mainKatID DESC LIMIT 3

Use a subquery that gets the oldest year award for each mainID. Combine that with the non-year awards using UNION.
SELECT v.pilotID, v.auszBereichID, v.auszTypID, v.gameID, v.auszDatum, m.mainGrafik, m.mainName
FROM zg15_auszeichnungen_vergeben AS v
LEFT JOIN (
SELECT * FROM zg15_auszeichnungen_main
WHERE mainKatID != 11
UNION
SELECT m1.*
FROM zg15_auszeichnungen_main AS m1
JOIN (SELECT mainID, MAX(mainPunkte) AS maxPunkte
FROM zg15_auszeichnungen_main
WHERE mainKatID = 11
GROUP BY mainID) AS m2
ON m1.mainID = m2.mainID AND m1.mainPunkte = m2.maxPunkte
WHERE m1.mainKatID = 11) AS m
ON v.auszMainID = m.mainID
WHERE v.pilotID = '$pilotID'
AND v.auszBereichID = 6
AND v.auszTypID = 100
AND v.gameID = 1
ORDER BY v.auszDatum;

Related

Get last 5 rows from Table for each user [duplicate]

This question already has answers here:
Select first row in each GROUP BY group?
(20 answers)
Closed 4 years ago.
I need you help with this problem.
Scenario:
Users can vote any number of songs, but I only want to select the last 5 votes per user. I do not want to select the last 5 votes.
Table structure:
Example:
3 users
Karl, voted 10 songs
Robert, voted 6 songs
Joanne, voted 3 songs
I want to get Karls last 5 votes, Roberts last 5 votes and Joannes 3 votes.
Current SQL query:
SELECT songs.genre, songs.title, songs.band, COUNT(*) AS anzahlVotes, users.name
FROM T_Songs AS songs
RIGHT JOIN T_Votes AS votes ON songs.P_Song_id = votes.F_Song_id
LEFT JOIN T_Users AS users ON votes.F_User_id = users.P_User_id
WHERE votes.P_Vote_id IN (
SELECT P_Vote_id
FROM T_Votes
GROUP BY F_User_id
HAVING P_Vote_id > MAX(P_Vote_id)-5
);
But this query doesn't return the right vote count.
Solution (Thanks to Gordon Linoff and Paul Spiegel):
SELECT songs.genre, songs.title, songs.band, COUNT(*) AS anzahlVotes, users.name
FROM T_Songs AS songs
RIGHT JOIN T_Votes AS votes ON songs.P_Song_id = votes.F_Song_id
LEFT JOIN T_Users AS users ON votes.F_User_id = users.P_User_id
WHERE users.nobility_house IS NOT NULL
AND votes.P_Vote_id >= coalesce(
(select votes2.P_Vote_id
from T_Votes votes2
where votes2.F_User_id = votes.F_User_id
order by votes2.P_Vote_id desc
limit 1 offset 4
), 0)
GROUP BY votes.F_User_id
Assuming "last 5" means the five with the highest ids, you can do:
select v.*
from t_votes v
where v.p_vote_id >= (select v2.p_vote_id
from t_votes v2
where v2.f_user_id = v.f_user_id
order by v2.p_vote_id desc
limit 1 offset 4
);
I'll let you figure out how to bring in the columns from the other tables.
EDIT:
If there are fewer than 5 rows:
select v.*
from t_votes v
where v.p_vote_id >= coalesce( (select v2.p_vote_id
from t_votes v2
where v2.f_user_id = v.f_user_id
order by v2.p_vote_id desc
limit 1 offset 4
), p_vote_id
);
You can filter with a join on the same table :
SELECT songs.genre, songs.title, songs.band, COUNT(*) AS anzahlVotes, users.name
FROM T_Songs AS songs
RIGHT JOIN T_Votes AS votes ON songs.P_Song_id = votes.F_Song_id
LEFT JOIN T_Users AS users ON votes.F_User_id = users.P_User_id
LEFT JOIN (
SELECT F_User_id, Max(P_Vote_id)-5 as MaxVoteId
FROM T_Votes
GROUP BY F_User_id
) DF ON ((DF.F_User_id = votes.F_User_id) AND (P_Vote_id >= MaxVoteId));

Counting entry in a column MySQL and display counts

I would want to count entries in a column and display the count beside it.
However, I'm clueless on how can I do it.
Desired output:
arrangement_number tray_no rl_type flag(count of occurrence)
------------------ ------- ---- ----
2774818 381001 R 3
2774818 381001 R 3
2774818 381001 L 3
2778470 405128 R 1
2779702 265265 R 2
2779702 265265 R 2
I'm currently trying queries using #variables but I still cant get it right.
each row are unique and I need them not to be grouped.
Update: Expanded Table added source code
Note: I'm currently joining 5 tables now
Actual Query:
SELECT
log.arrangement_number,
header.tray_number,
detail.rl_type,
-- some more fields here
FROM
log
INNER JOIN
header ON log.arrangement_number = header.rxarrangement_number
AND log.production_place_code = header.production_place_code
INNER JOIN
detail ON log.arrangement_number = detail.rxarrangement_number
AND log.production_place_code = detail.production_place_code
INNER JOIN
deliveryperiod ON log.arrangement_number = deliveryperiod.arrangement_number
AND log.production_place_code = deliveryperiod.production_place_code
AND detail.rl_type = deliveryperiod.rl_type
INNER JOIN
calc ON calc.arrangement_number = log.arrangement_number
AND calc.production_place_code = log.production_place_code
AND deliveryperiod.rl_type = calc.rl_type
AND detail.rl_type = calc.rl_type
WHERE
header.status_code IN ('20' , '21')
AND log.process_code = '12'
AND deliveryperiod.process_code_current = '12'
AND deliveryperiod.sub_process_code_current IN ('100' , '105')
AND lot_number = '120131'
ORDER BY log.lot_number , log.sequence_number , deliveryperiod.rl_type DESC
SELECT t1.tray_no,
t2.flag
FROM yourTable
INNER JOIN
(
SELECT tray_no, COUNT(*) AS flag
FROM yourTable
GROUP BY tray_no
) t2
ON t1.tray_no = t2.tray_no
try this...
SELECT tray_no, COUNT(*) 'flag'
FROM table1
GROUP BY tray_no

Limit query for each group

I have this query:
select pl.photo_id, pl.user_id, pl.liker_id, p1.filename user_filename, p2.filename liker_filename
FROM photo_likes pl
left join photos p1 on (pl.photo_id = p1.photo_id)
left join photos p2 on (pl.liker_id = p2.user_id and p2.avatar = 1)
where pl.user_id = $id order by pl.liker_id, pl.date_liked desc
It gets the correct data, but I would like to modify it to limit the data. So, in a nut shell, this query will get all the likes from all the people that liked a photo of theirs, it works great, this can grab lots of photos for each person. But I want to limit it to get only 5 from each person:
So, say user A likes 10 of my photos, user B likes 8 of my photos, and user C likes 2 of my photos, I only want the last 5 from user A, the last 5 from user B and the last 2 from user C. If that makes sense, how can this be done?
The query you have is good, but I'm wrapping that and using MySQL variables to check each return variable and increase the sequence per each "liker". When the liker changes, set the sequence back to 1.... Then, apply HAVING < 6 for the sequence. You can't do it in the WHERE clause because you want EVERY record to be QUALIFIED which keeps updating the #likeSeq and #lastLiker. Only AFTER that is done, the HAVING says... AFTER that, if the seq is greater than you 5 cap, it throws it out.
per alternate rows being included per your print-screens...
select
AllRanks.*
from
( select
PreQualified.*,
#likeSeq := if( PreQualified.Liker_ID = #lastLiker, #likeSeq +1, 1 ) as Seq,
#lastLiker := PreQualified.Liker_ID
from
( select
pl.photo_id,
pl.user_id,
pl.liker_id,
p1.filename user_filename,
p2.filename liker_filename
FROM
photo_likes pl
left join photos p1
on pl.photo_id = p1.photo_id
left join photos p2
on pl.liker_id = p2.user_id
and p2.avatar = 1
where
pl.user_id = $id
order by
pl.liker_id,
pl.date_liked desc ) PreQualified,
( select #lastLiker := 0,
#likeSeq := 0 ) sqlvars
) AllRanks
where
AllRanks.Seq < 6
Could you wrap your joined tables in a sub query?
select ...
from photo_likes
left join photos p1 ...
left join (select p2.filename liker_filename from photos where p1.liker_id = p2.user_id and avatar = 1 LIMIT 5) p2
where ...

Update Table by Join and Group by

A Company has many Reviews which has Rating Column itself.
CompID Ratig
12 3
13 3
17 4
22 4
23 5
24 3
28 3,2
This is what I need to be set to each company by id. Now Rating In Company Column is NULL.
I've written something like this:
UPDATE Companies c
JOIN Reviews r on c.CompanyID = r.CompanyID
SET c.Rating = AVG(r.rating)
group by r.CompanyID
This should do what you want using a simple nested query, in this case probably simpler than a JOIN.
UPDATE Companies
SET Rating =
(SELECT AVG(Rating)
FROM Ratings
WHERE Companies.CompanyId = Ratings.CompId)
Simple SQLfiddle demo here.
EDIT: If you really want to use a JOIN/UPDATE FROM, it'd look something like this;
UPDATE c
SET c.Rating = r.Rating
FROM Companies c
JOIN (SELECT AVG(Rating) Rating, CompID FROM Ratings GROUP BY CompId) r
ON c.CompanyId = r.CompId
At least to me, somewhat more complicated to read, and afaik it only works on SQL Server, but here's the SQLfiddle for that too :)
UPDATE ComisionesxColaboradorxLineaPrescripciones
SET CANTIDAD_PRODUCTOS_CORE_CUMPLE = CANTIDAD
FROM #ComisionesxColaboradorxLineaPrescripciones ComisionesxColaboradorxLineaPrescripciones
INNER JOIN
(SELECT TAB_L.COD_COLAB AS COD_COLAB,TAB_L.TIPO_COLABORADOR AS TIPO_COLABORADOR, COUNT(TAB_P.COD_SEG) AS CANTIDAD
FROM #ComisionesxColaboradorxLineaPrescripciones TAB_L
INNER JOIN #ComisionesxColaboradorxLineaxProductoPrescripciones TAB_P
ON TAB_L.COD_COLAB=TAB_P.COD_COLAB AND
TAB_L.TIPO_COLABORADOR=TAB_P.TIPO_COLABORADOR
GROUP BY TAB_L.COD_COLAB,TAB_L.TIPO_COLABORADOR
) AGRUPADO
ON ComisionesxColaboradorxLineaPrescripciones.COD_COLAB = AGRUPADO.COD_COLAB AND
ComisionesxColaboradorxLineaPrescripciones.TIPO_COLABORADOR = AGRUPADO.TIPO_COLABORADOR

MySQL SELECT DISTINCT ORDER BY problem

To begin with I have 4 tables I am dealing with.
I have a classes table that is a 1->N relationship with a sections table which also has a 1->N relationship with a lessons table.
So to put it in perpective:
Classes
Sections
Lessons
The last table is an activityLog, when the student accesses a lesson this is recorded using the following:
ActivityLog Row -> actorID (user ID), classID, sectionID, lessonID
I want to pull out the last 5 unique lessons the student has visited. I tried using both DISTINCT and GROUP BY without success.
The same records are being returned each time, not the latest classes that they have visited.
Using GROUP BY
SELECT activityLog.actorID, activityLog.activityDate,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
GROUP BY activityLog.lessonID
ORDER BY activityLog.activityDate DESC
LIMIT 5
Using DISTINCT
SELECT DISTINCT activityLog.actorID,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
ORDER BY activityLog.activityDate DESC
LIMIT 5
I cannot figure out why the latest records are not being displayed.
Based on your change, how does this suit you?
SELECT activityLog.actorID, activityLog.activityDate,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
AND activityLog.activityDate = (SELECT MAX(activityDate) FROM activityLog AS lookup WHERE lessonID = activityLog.lessonID)
ORDER BY activityLog.activityDate DESC
LIMIT 5
Based on your description, I'm not sure why you're using LEFT JOIN, but I've left it in just in case.
Try group by like below
GROUP BY activityLog.classID,activityLog.sectionID,activityLog.lessonID
I think it will work, or just sent me create scripts for these I will create that query
Well, there's got to be a datetime in the ActivityLog I hope... so Try this:
Select s.Name, c.ClassName
From Students s
left Join On Classes c
On c.ClassId In
(Select Distinct ClassId From Classes
Where (Select Count(Distinct ClassId) From Classes ic
Join ActivityLog l On l.UserId = s.UserId
And l.ClassId = c.ClassId
Where classId = c.ClassId
And activityDateTime > l.activityDateTime)
< 5)