使用JOIN和多个条件的SQL查询

Sve*_*ven 5 sql select join

我在制定SQL查询时遇到了麻烦.我执行以下操作:

SELECT *
FROM tasks
LEFT JOIN plans
ON plans.task_id = tasks.id
Run Code Online (Sandbox Code Playgroud)

并获得此结果集:

task.id task.description  plan.id plan.task_id plan.date
-------|-----------------|-------|------------|------------
   1    Foo                  1         1        1998-01-01
   2    Foobar               2         2        2012-02-25
   2    Foobar               3         2        2012-12-12
   3    Foobass              4         3        2012-12-24
   4    Bassbar
                       ... and lots of more records
Run Code Online (Sandbox Code Playgroud)

今天是2012-08-03.我希望所有任务都具备以下条件:任务从未计划过,或者任务已经过去,但没有未来的计划.

在上面的示例中,以下任务满足此条件:

  • 1 Foo
  • 4 Bassbar

有什么建议?提前致谢!

Jon*_*onH 1

SELECT *
FROM tasks
LEFT JOIN plans
ON plans.task_id = tasks.id
WHERE plan.week IS NULL OR (plan.week < DATEPART(week, GetDate()) AND plan.Year = YEAR(GETDATE())
Run Code Online (Sandbox Code Playgroud)

您不应该使用SELECT *,明确写出您需要的每一列。您没有提到是否也有年份列,您必须处理周数和年份。如果你只处理一周,你就会得到多年的结果。

听起来你可以只使用任务描述???如果可以使用任务描述,为什么还要基于周列呢?

SELECT *
FROM tasks
LEFT JOIN plans
ON plans.task_id = tasks.id
WHERE tasks.description = 'Past' OR tasks.description = 'Not planned'
Run Code Online (Sandbox Code Playgroud)

啊哈,我现在明白你的数据了,你可以有多个任务,但周数不同。这很简单,只需使用查询找到任务的 MAX(Week#) GROUP BY,然后执行查询,我会把它写下来给我一分钟......

  CREATE TABLE #MyTest
(
 TaskID int,
 TaskYear int,
 TaskWeek int
)

INSERT INTO #MyTest(TaskID,TaskYear,TaskWeek)
VALUES (1, 2012, 4)
INSERT INTO #MyTest(TaskID,TaskYear,TaskWeek)
VALUES (2, 2012, 5)
INSERT INTO #MyTest(TaskID,TaskYear,TaskWeek)
VALUES (2, 2012, 36)
INSERT INTO #MyTest(TaskID,TaskYear,TaskWeek)
VALUES (3, 2012, 36)
INSERT INTO #MyTest(TaskID,TaskYear,TaskWeek)
VALUES (4, 2012, NULL)
INSERT INTO #MyTest(TaskID,TaskYear,TaskWeek)
VALUES (6, 2011, 5)
INSERT INTO #MyTest(TaskID,TaskYear,TaskWeek)
VALUES (6, 2010, 36)

SELECT
    TaskID,
    MAX(TaskWeek) AS WeekNumber,
    TaskYear
FROM
  #MyTest
GROUP BY 
    TaskID,
    TaskWeek,
    TaskYear
HAVING MAX(TaskWeek) < DatePart(week, GetDate()) OR MIN(TaskWeek) IS NULL

DROP TABLE #MyTest
Run Code Online (Sandbox Code Playgroud)

task.id现在,这将为您提供具有最大周数的唯一行。

最后结果

根据您的最终意见:

将其复制并粘贴到 sql management studio 中,我已经为您注释了:

CREATE TABLE #MyTest
(
 TaskID int,
 TaskDate datetime
)

--test for only in the past NOTHING in the future
INSERT INTO #MyTest(TaskID, TaskDate)
VALUES (1, '1998-01-01')

--test for planned in the future NOTHING in the past
INSERT INTO #MyTest(TaskID,TaskDate)
VALUES (3, '2012-12-24')

--test for no plan as all (IS NULL)
INSERT INTO #MyTest(TaskID,TaskDate)
VALUES (4, null)

--test for planned in the past but has an upcoming event in the future
INSERT INTO #MyTest(TaskID,TaskDate)
VALUES (6, '2011-12-23')
INSERT INTO #MyTest(TaskID,TaskDate)
VALUES (6, '2012-12-23')
INSERT INTO #MyTest(TaskID,TaskDate)

--test for planned in the past, NO upcoming event in the future
VALUES (8, '2012-1-23')
INSERT INTO #MyTest(TaskID,TaskDate)
VALUES (8, '2012-6-23')

--result should show:
-- task id = 1 (because of: performed in past but nothing in the future)
-- task id = 4 (because of: no plan at all) 
-- task id = 8 (because of: only past)

SELECT
    TaskID,
    YEAR(TaskDate) AS TheYear,
    DatePart(week, TaskDate) AS WeekNumber
FROM
  #MyTest
WHERE 
--handle no planning of a task...
((TaskDate IS NULL)
--eliminate any task id that is out in the future
OR TaskID NOT IN (SELECT TaskID FROM #MyTest WHERE TaskDate > GetDate()))
GROUP BY
    TaskID,
    Year(TaskDate),
    DatePart(week, TaskDate)

DROP TABLE #MyTest
Run Code Online (Sandbox Code Playgroud)