从不同的子查询中选择top 1来实现基本项目路由功能

时间:2018-01-03 03:28:17

标签: sql-server

我正在尝试实现一个非常简单的路由系统,它允许项目根据相关表的路由信息​​从一个步骤转到另一个步骤。我的ASP.NET方法应该基于数据库结果进行下一步,以避免任何愚蠢的硬编码值。

有一个表包含活动步骤(所有步骤“要做”或不做,位:1或0),另一个包含已完成的步骤。根据这些信息,我相信我应该能够从包含所有活动步骤的表中选择前1(下一步),其中stepID不在已完成的stepID列表中。

我在纸上尝试了这个并且它有意义,我也尝试从详细查询到大查询,我应该返回下一步(前1)。底层查询工作,但是,我的大查询有问题应该返回前1项(下一步)。我总是收到以下错误:

  

“消息156,级别15,状态1.关键字附近的语法不正确   '哪里'。消息156,级别15,状态1.关键字附近的语法不正确   '不'。 (第4行)“

表概述如下。

路线包含要完成的所有步骤(或不是 - > 0)

itemID |routeID |stepID |stepScheduled |
-------|--------|-------|--------------|
1      |1       |10     |1             |
2      |1       |20     |1             |
3      |1       |30     |1             |
4      |1       |40     |1             |
5      |1       |50     |1             |
6      |1       |60     |1             |
7      |1       |70     |1             |
8      |1       |80     |1             |
9      |1       |90     |1             |
10     |1       |100    |1             |
----------------------------------------

包含已完成步骤的 Steps_Completed (如果此项尚未完成任何步骤,则可能为空)。

completionID |sampleID |stepID |userName |completionDT        |stationID     |
-------------|---------|-------|---------|--------------------|--------------|
1            |1        |10     |Me       |2017-12-28 10:04:41 |workstation 1 |
------------------------------------------------------------------------------

查询我正在尝试返回上面提到的错误消息:

SELECT TOP 1 stepID FROM 
(SELECT [stepID] **Routes** WHERE [routeID] = 1 AND [stepScheduled] = 1) 
WHERE stepID NOT IN (SELECT stepID FROM **Steps_Completed** WHERE sampleID = 
1);

()中的子查询在单独执行时起作用并返回预期值:

  • (从路线选择[stepID] WHERE [routeID] = 1 AND [stepScheduled] = 1) 返回第一个表中显示的所有行(所有“要做”)

  • (SELECT stepID FROM Steps_Completed WHERE sampleID = 1) 返回已完成的所有行,如果尚未记录任何内容,则返回空结果。

想法是对“路线”列表进行基本的“减法”,“减去”已完成的步骤,然后选择剩余列表的前1项。由于stepID列表可以由ASC订购,因此前1项应该是我的结果。

问题似乎与“WHERE stepID NOT IN”部分有关。

3 个答案:

答案 0 :(得分:0)

以下是您当前查询的即时修复:

SELECT TOP 1 [stepID]
FROM Routes
WHERE
    [routeID] = 1 AND
    [stepScheduled] = 1 AND
    [stepID] NOT IN (SELECT stepID FROM Steps_Completed WHERE sampleID = 1)
ORDER BY
    [stepID];

另一种表达方法是使用左连接:

SELECT TOP 1 r.stepID
FROM Routes r
LEFT JOIN Steps_Completed s
    ON r.routeID = s.sampleID AND
       r.stepID = s.stepID
WHERE
    r.routeID = 1 AND
    r.stepScheduled = 1 AND
    s.sampleID IS NULL
ORDER BY
    r.stepID;

此处需要注意的一点是,我们通常必须使用ORDER BYTOP。否则," top"没有很好地定义,因为SQL表没有内部顺序。另外,我认为你不一定要在这里使用子查询,所以我已将其删除了。

答案 1 :(得分:0)

使用别名:

SELECT TOP 1 stepID FROM 
(SELECT [stepID] from Routes WHERE [routeID] = 1 AND [stepScheduled] = 1) as a
WHERE stepID NOT IN (SELECT stepID FROM Steps_Completed WHERE sampleID = 
1);

答案 2 :(得分:0)

SELECT stepID 
FROM Routes
WHERE stepID = (SELECT MIN(stepId) 
                FROM Routes r
                LEFT JOIN Steps_Completed sc
                ON r.stepID = sc.stepID
                WHERE [routeID] = 1 
                      AND [stepScheduled] = 1
                      AND sc.stepID is null)