user_id user_name
---------------------
1 User A
2 User B
user_id track
---------------------
1 no
2 no
user_id date_of_application date_ended grade status
---------------------------------------------------------------
1 2011-01-01 2011-02-28 1.0 Ended
1 2011-02-02 2011-03-28 1.0 Ended
1 2011-03-03 2011-04-28 (1.5) Ended
2 2011-01-01 2011-02-20 2.0 Ended
2 2011-02-02 2011-03-11 2.5 Ended
2 2011-03-03 2011-04-28 (1.0) Ended
1 2011-05-10 - - Pending
2 2011-05-15 - - Pending
我想在这里完成的是检索所有行 WHERE状态为'待定',并且每个检索到的行的成绩列的值为最新成绩的值(换句话说,带有最新日期_ 的行),(在上面的括号中),此特定用户(或行)的状态为“已结束” )。
另外,我需要将结果的前10行设置为等级ASC 。然后将后续行(第11行直到最后一行)排序为 date_of_application ASC 。
显然,SQL查询不是我最强的区域,因此我不确定使用2个或更多查询执行这些ORDER BY是否更好(或仅可能)。但是我更喜欢使用单个查询来完成此操作。
user_id user_name date_of_application grade status track
--------------------------------------------------------------------
1 User A 2011-05-10 (1.5) Pending no
2 User B 2011-05-15 (1.0) Pending no
我到目前为止工作代码[减去可能的拼写错误],(并列出了要应用的附加内容):
查询:
SELECT users.user_name,
t.track,
a.user_id,
a.date_of_application,
a.status,
(SELECT ae.grade
FROM applications AS ae
WHERE ae.status = 'Ended'
AND ae.user_id = a.user_id
LIMIT 1) AS grade
FROM users
JOIN applications AS a ON users.user_id = a.user_id
JOIN tracking AS t ON users.user_id = t.user_id
WHERE a.status = 'Pending'
ORDER BY grade ASC
答案 0 :(得分:2)
你可能在这里尝试在一个查询中做太多。
无论如何,如果你想要伤害你的眼睛:
select a.* from
(
SELECT u.user_name,
a.user_id,
a.date_of_application,
td.grade,
a.status,
t.track
FROM users u
JOIN applications AS a ON u.user_id = a.user_id
JOIN tracking AS t ON u.user_id = t.user_id
LEFT OUTER JOIN
(
select ap.user_id,ap.grade
from applications ap
inner join
(select a.user_id,max(date_ended) as max_ended_date
from applications a
where a.status = 'Ended'
group by a.user_id
) md on md.user_id = ap.user_id and ap.date_ended = md.max_ended_date
) as td on u.user_id = td.user_id
WHERE a.status = 'Pending'
ORDER BY cast(replace(replace(td.grade,'(',''),')','') as decimal(12,2)),u.user_id ASC
LIMIT 10
) a
WHERE grade is not null
UNION ALL
select b.* from
(
SELECT u.user_name,
u.user_id,
a2.date_of_application,
td.grade,
ifnull(a2.status,'No applications yet') as status,
t2.track
FROM users u
LEFT OUTER JOIN (select user_id,date_of_application,status from applications where status = 'Pending') AS a2 ON u.user_id = a2.user_id
JOIN tracking AS t2 ON u.user_id = t2.user_id
LEFT OUTER JOIN
(
select ap.user_id,ap.grade
from applications ap
inner join
(select a.user_id,max(date_ended) as max_ended_date
from applications a
where a.status = 'Ended'
group by a.user_id
) md on md.user_id = ap.user_id and ap.date_ended = md.max_ended_date
) as td on u.user_id = td.user_id
where u.user_id not in (
select t1.user_id
from (
select ap1.user_id,ap1.grade
from applications ap1
inner join
(select a1.user_id,max(date_ended) as max_ended_date
from applications a1
where a1.status = 'Ended'
group by a1.user_id
) md1 on md1.user_id = ap1.user_id and ap1.date_ended = md1.max_ended_date
order by cast(replace(replace(ap1.grade,'(',''),')','') as decimal(12,2)),md1.user_id asc
limit 10
) as t1
)
ORDER BY status desc,a2.date_of_application ASC
) b;
这确实做出以下假设:
users
和tracking
中的每个user_id始终只有一行
a
表修改强>
稍微解释一下这个问题:
内联视图别名ORDER BY cast(replace(replace(td.grade,'(',''),')','') as decimal(12,2)),u.user_id ASC
(又名“上半部分”)根据最近的“已结束”等级提升,返回前10名用户的列表。请注意查询的以下部分从成绩中删除任何括号,将结果数字转换为小数位数到2位小数,并按等级递增,然后,如果等级成绩相同,则按user_id排序:
b
内联视图a
与内嵌视图DESC
几乎相同,不同之处在于排除了出现在上半部分的用户,并按状态ASC
对结果进行排序(以移动这些用户)没有应用程序到列表底部)和申请日期{{1}}。
答案 1 :(得分:1)
这应该对你有用...为了弄清楚发生了什么,你必须从查询的最内部开始。对于每个用户,找到最高的“待定”日期(因为如您所述,只有一个),以及最后一个“结束”类日期。按用户分组。这将保证每个用户一条记录,预先计算为PreQuery。
接下来,按用户和上次结束日期自行联接回应用程序表TWICE ...一次,然后按用户和上次挂起日期进行。通过LEFT JOIN,如果你只有一个人有一个应用程序但没有结束,他们将被包括在内......同样,如果只有一个完整的类没有更多的待处理申请,他们也将被包括在内。
从这些别名参考中拉出相应的列以获得成绩。虽然我们正在使用SQL变量,但使用此查询的顺序,DESCENDING将从1-n中获得最佳成绩而不考虑申请日期。
最后,取整个结果集并按照特殊顺序排序......按条件排序,如果用户的等级小于11,则使用其顺序。否则,让其他所有人按顺序为第一个订单分配相同的“11”值...之后,按申请日期排序。
小块依赖于前一组。这个不应该让你的头受伤,也不需要任何工会
select
QryRank.*
from
( select
PreQuery.User_ID,
usr.user_Name,
trk.Track,
PreQuery.LastEnded,
appEnd.Grade,
PreQuery.LastPend as Date_Of_Application,
@Rank := @Rank +1 UserRank
from
( select
app.user_id,
max( if( app.status = "Ended", date_ended, null ) ) as LastEnded,
max( if( app.status = "Pending", app.date_of_application, null )) LastPend
from
Applications app
group by
app.user_id ) PreQuery
LEFT JOIN Applications appEnd
on PreQuery.User_ID = appEnd.User_ID
AND PreQuery.LastEnded = appEnd.date_ended
LEFT JOIN Applications appPend
on PreQuery.User_ID = appPend.User_ID
AND PreQuery.LastPend = appPend.date_of_application
join Users usr
on PreQuery.user_id = usr.user_id
join Tracking trk
on PreQuery.user_id = trk.user_id,
( select @Rank := 0 ) sqlvars
order by
appEnd.Grade DESC ) QryRank
order by
if( QryRank.UserRank < 11, QryRank.UserRank, 11 ),
QryRank.Date_Of_Application