简体   繁体   中英

How do I write this tricky SQL query?

[FYI, this is not homework — I guess everyone thinks that because I made an effort to format my question in a simple readable form? Again, not homework. I'm at work, and just trying to learn. Thanks.]

I'm very stuck on a tricky one. I'm a Java guy, I'm not a SQL guy, so any help with this is GREATLY appreciated!

I have a PROJECT table and a TASK table like so:

**PROJECT**
projectId
name

PROJECT has many TASKs:

**TASK**
taskId
projectId
description
userId // the user who is assigned the task
status // either "IN_PROGRESS" or "COMPLETE"
sequence // the numeric sequence of the TASK in the PROJECT

For example:

Project
   projectId=100
   name="Build House"
Task
   taskId=250 // task IDs are not necessary in numerical order
   sequence=1
   description="Pour Foundation"
   userId=55
   status="COMPLETE"
Task
   taskId=240
   sequence=2
   description="Build walls"
   userId=56
   status="COMPLETE"
Task
   taskId=260
   sequence=3
   description="Install windows"
   userId=57
   status="IN_PROGRESS"
Task
   taskId=245
   sequence=4
   description="Build roof"
   userId=58
   status="IN_PROGRESS"

I need two queries:

(1) For a given projectId, get the 'current task'. The current task is the task number with the smallest sequence number which is not complete. In my example, getCurrentTask(projectId=100) would return taskId 260 (because it's the first one that is incomplete).

(2) For a given userId, get the list of projects where he is assigned to a 'current task'. In my example, getProjectsForUserId(userId=57) would return projectId 100; getProjectsForUserId(userId=58) would return nothing.

SELECT min(taskID) FROM Task WHERE ProjectID = ? and status <> "COMPLETE";

SELECT projectID FROM 
Tasks T INNER JOIN
(SELECT min(taskID) as taskID, projectID FROM Task GROUP BY projectID WHERE status <> "COMPLETE")
AS CT on CT.taskID = T.taskID
WHERE T.userId = ?'

EDIT

The queries below order by sequence, instead of TaskID.

SELECT taskID from Task T INNER JOIN
(SELECT min(sequence) as sequence, projectID FROM Task GROUP BY projectID WHERE status <> "COMPLETE")
   AS CT on CT.sequence = T.sequence AND CT.projectID = T.projectID
WHERE T.projectID = ?;

SELECT projectID FROM 
Task T INNER JOIN
(SELECT min(sequence) as sequence, projectID FROM Task GROUP BY projectID WHERE status <> "COMPLETE")
   AS CT on CT.sequence = T.sequence AND CT.projectID = T.projectID
WHERE T.userID = ?;
SELECT * FROM TASK
LEFT OUTER JOIN PROJECT ON 
    TASK.PROJECTID=PROJECT.PROJECTID 
WHERE TASK.STATUS='IN_PROGRESS' 
  AND PROJECT.PROJECTID=?
ORDER BY SEQUENCE ASC

First Query (updated):

SELECT taskId FROM `task` 
WHERE `projectId`=100 AND `status` = "IN_PROGRESS" 
ORDER BY `sequence`
LIMIT 1

Second one:

SELECT DISTINCT(projectId) FROM task 
WHERE userId=57 AND `status` = "IN_PROGRESS"
ORDER BY `sequence`

PS Didn't added any joins to project table, because in your task you asked only about ids.

If it were homework, I'd give these hints:

(1): A simple query over Tasks will do. (You know the project ID after all, right?) Use aggregate functions and a WHERE clause.

(2): Try quering Projects using a WHERE EXISTS ... construct. DISTINCT might come in handy, too.

EDIT: You don't even need to touch Projects for the second query, too. The queries posted by @true look correct.

EDIT^2: ...but @true's query don't consider the subtlety that only the "current" tasks are of interest.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM