SQL Server - 检查是否存在具有特定值的记录

时间:2011-12-20 18:38:39

标签: sql-server

我在SQL Server中遇到了一个非常简单的问题:

用户可以有12个项目,表格中包含ID和Slot(插槽为0-11)。拾取物品时,应将其放入最低的空槽中。

我正在使用以下脚本,但它在第一个使用的插槽后返回第一个空插槽:

SELECT coalesce ((SELECT MIN(Slot) + 1 FROM Items N1 WHERE N1.name = 'abc'
AND NOT EXISTS(SELECT * FROM Items N2 WHERE N2.name = 'abc'
AND N2.Slot = N1.Slot + 1) AND Slot<11),0)

我需要脚本来找到尚不存在的最低插槽。希望它有意义:))

示例 - 如果表包含以下记录,则不起作用,返回5(应返回0):

ID  Slot Name
10    3  abc
11    4  abc

使用此数据,它确实正确返回2.

ID  Slot Name
10    0  abc
11    1  abc

脚本应返回1,因为这是第一个未使用的数字(Slot)低于11。

4 个答案:

答案 0 :(得分:1)

  SELECT coalesce (
                    (SELECT MIN(N1.Slot) + 1 
                       FROM Items N1
                            LEFT OUTER JOIN Items N2 ON N1.Slot+1 = N2.Slot
                      WHERE N1.name = 'abc'
                        AND N2.Slot IS NULL
                        AND N1.Slot < 11)
                   ,0)

答案 1 :(得分:1)

DECLARE @Items TABLE (
    ID INT,
    Slot INT,
    Name VARCHAR(50)
)

INSERT INTO @Items VALUES (10, 0, 'ABC')
INSERT INTO @Items VALUES (11, 2, 'ABC')
INSERT INTO @Items VALUES (12, 3, 'ABC')

INSERT INTO @Items VALUES (13, 0, 'EFG')
INSERT INTO @Items VALUES (14, 1, 'EFG')
INSERT INTO @Items VALUES (15, 2, 'EFG')
INSERT INTO @Items VALUES (16, 3, 'EFG')
INSERT INTO @Items VALUES (17, 4, 'EFG')

SELECT
    i.Name,
    MIN(i.Slot + 1) AS LowestSlot
FROM
    @Items i 
    LEFT JOIN @Items i2 ON i2.Slot = i.Slot + 1 AND i2.Name = i.Name
WHERE
    -- i.Slot + 1 < 11 or, i.Slot < 10
    i.Slot < 10 AND
    i2.ID IS NULL
GROUP BY
    i.Name

答案 2 :(得分:1)

问题的主要困难在于它需要发明数据。 MSSQL如何知道您的插槽编号为0 - 11?为什么不-3 - 19?显然,答案是“因为你这么说”,但你需要告诉MSSQL。

在MSSQL中,您可以创建一个表变量来保存基本的插槽信息,然后将Items表连接起来以确定哪些是空的

DECLARE @tv TABLE (
    ID INT
)

INSERT INTO @tv
VALUES
(0),
(1),
(2),
(3),
(4),
(5),
(6),
(7),
(8),
(9),
(10),
(11)

SELECT
    MIN(t.ID) + 1 AS EmptySlot
FROM
    @tv t
    LEFT JOIN Item i
        ON t.ID = i.ID
WHERE
    ISNULL(i.Slot, 0) = 0

答案 3 :(得分:0)

@ simon查询的变体。它适用于SQL-Server 2008:

SELECT
    MIN(t.Slot) AS EmptySlot
FROM
      ( VALUES
        (0), (1), (2), (3),
        (4), (5), (6), (7),
        (8), (9), (10), (11) 
      ) AS t(Slot)
    LEFT JOIN
        Items AS i
      ON i.Slot = t.Slot
WHERE
    i.Slot IS NULL

或:

SELECT
    MIN(t.Slot) AS EmptySlot
FROM
  ( VALUES
    (0), (1), (2), (3),
    (4), (5), (6), (7),
    (8), (9), (10), (11) 
  ) AS t(Slot)
WHERE 
    NOT EXISTS
      ( SELECT *
        FROM Items AS i
        WHERE i.Slot = t.Slot
      )