循环记录集并使用结果执行另一个 SQL 选择并返回结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15286255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 14:08:18  来源:igfitidea点击:

Loop through a recordset and use the result to do another SQL select and return the results

sqlsql-serverstored-procedures

提问by J K

I am completely new to stored procedure. This time, I need to create a stored procedure in MS SQL.

我对存储过程完全陌生。这一次,我需要在 MS SQL 中创建一个存储过程。

Let's say I have the following table.

假设我有下表。

     Table name: ListOfProducts  
      --------------------------
       SomeID, ProductID  

         34, 4
         35, 8
         35, 11

How do I pass in a SomeID. Use this SomeID to select a recordset from table, ListOfProducts. Then loop through this record set.

如何传入 SomeID。使用此 SomeID 从表 ListOfProducts 中选择记录集。然后循环遍历这个记录集。

Let's say I pass in SomeID = 35.

假设我传入 SomeID = 35。

So, the record set will return 2 records with SomeID 35. In the loop, I will get ProductID 8 and 11, which will be used to do another select from another table.

因此,记录集将返回 2 条 SomeID 为 35 的记录。在循环中,我将获得 ProductID 8 和 11,这将用于从另一个表中进行另一个选择。

The stored procedure should return the results from the 2nd select.

存储过程应该返回第二次选择的结果。

How can I do this in MS SQL stored procedure?

如何在 MS SQL 存储过程中执行此操作?

Sorry, for this newbie question. Thanks for any help.

对不起,对于这个新手问题。谢谢你的帮助。

回答by Ken Clark

If you want looping through the records. You can do like:

如果你想遍历记录。你可以这样做:

--Container to Insert Id which are to be iterated
Declare @temp1 Table
(
  tempId int
)
--Container to Insert records in the inner select for final output
Declare @FinalTable  Table
(
  Id int,
  ProductId int
)

Insert into @temp1 
Select Distinct SomeId From YourTable

-- Keep track of @temp1 record processing
Declare @Id int
While((Select Count(*) From @temp1)>0)
Begin
   Set @Id=(Select Top 1 tempId From @temp1)

   Insert Into @FinalTable 
   Select SomeId,ProductId From ListOfProducts Where Id=@Id

   Delete @temp1 Where tempId=@Id
End

Select * From @FinalTable

回答by digscoop

There is probably no point in writing an explicit loop if you don't need to preform some action on the products that can't be done on the whole set. SQL Server can handle stuff like this much better on its own. I don't know what your tables look like, but you should try something that looks more like this.

如果您不需要对无法在整个集合上完成的产品执行某些操作,那么编写显式循环可能没有意义。SQL Server 可以自己更好地处理这样的事情。我不知道你的桌子是什么样的,但你应该尝试一些看起来更像这样的东西。

CREATE PROC dbo.yourProcName 
   @SomeID int
AS 
BEGIN
    SELECT
        P.ProductId,
        P.ProductName
    FROM
        Product P
        JOIN 
            ListOfProducts LOP
            ON LOP.ProductId = P.ProductId
    WHERE
        LOP.SomeId = @SomeID 
END

回答by micabug

I had to do something similar in order to extract hours from a select resultset start/end times and then create a new table iterating each hour.

我必须做一些类似的事情才能从选择的结果集开始/结束时间中提取小时数,然后创建一个每小时迭代的新表。

DECLARE @tCalendar TABLE
(
    RequestedFor VARCHAR(50),
    MeetingType VARCHAR(50),
    RoomName VARCHAR(MAX),
    StartTime DATETIME,
    EndTime DATETIME
)

INSERT INTO @tCalendar(RequestedFor,MeetingType,RoomName,StartTime,EndTime)
SELECT req as requestedfor
      ,meet as meetingtype
      ,room as rooms
      ,start as starttime
      ,end as endtime

      --,u.datetime2 as endtime
    FROM mytable



        DECLARE @tCalendarHours TABLE
    (
        RequestedFor VARCHAR(50),
        MeetingType VARCHAR(50),
        RoomName VARCHAR(50),
        Hour INT
        )

    DECLARE @StartHour INT,@EndHour INT, @StartTime DATETIME, @EndTime DATETIME
    WHILE ((SELECT COUNT(*) FROM @tCalendar) > 0)   
    BEGIN
        SET @StartTime = (SELECT TOP 1 StartTime FROM @tCalendar)
        SET @EndTime = (SELECT TOP 1 EndTime FROM @tCalendar)
        SET @StartHour = (SELECT TOP 1 DATEPART(HOUR,DATEADD(HOUR,0,StartTime)) FROM @tCalendar)
        SET @EndHour = (SELECT TOP 1 DATEPART(HOUR,DATEADD(HOUR,0,EndTime)) FROM @tCalendar)
        WHILE @StartHour <= @EndHour
        BEGIN
            INSERT INTO @tCalendarHours
            SELECT RequestedFor,MeetingType,RoomName,@StartHour FROM @tCalendar WHERE StartTime = @StartTime AND EndTime = @EndTime
            SET @StartHour = @StartHour + 1
        END
        DELETE @tCalendar WHERE StartTime = @StartTime AND EndTime = @EndTime
    END

回答by parkerw262

Do something like this:

做这样的事情:

Declare @ID int

SET @ID = 35

SELECT
   p.SomeID
  ,p.ProductID
 FROM ListOfProducts p
  WHERE p.SomeID = @ID
 -----------------------
   --Or if you have to join to get it
  Declare @ID int

  SET @ID = 35

    SELECT
      c.SomeID
      ,p.ProductID
      ,p.ProductName

    FROM ListOfProducts p
    INNER JOIN categories c on p.ProductID = c.SomeID
    WHERE p.SomeID = @ID

回答by Aleksandr Fedorenko

You can use option with WHILEloop and BREAK/CONTINUEkeywords

您可以将选项与WHILE循环和BREAK/CONTINUE关键字一起使用

CREATE PROC dbo.yourProcName
@SomeID int
AS
BEGIN
  IF OBJECT_ID('tempdb.dbo.#resultTable') IS NOT NULL DROP TABLE dbo.#resultTable
  CREATE TABLE dbo.#resultTable
   (Col1 int, Col2 int)  
  DECLARE @ProductID int = 0
  WHILE(1=1)
    BEGIN
      SELECT @ProductID = MIN(ProductID) 
      FROM ListOfProducts 
      WHERE SomeID = @SomeID AND ProductID > @ProductID

      IF @ProductID IS NULL
      BREAK
      ELSE

      INSERT dbo.#resultTable
      SELECT Col1, Col2
      FROM dbo.yourSearchTable
      WHERE ProductID = @ProductID

      CONTINUE      
    END
  SELECT *
  FROM dbo.#resultTable 
END    

Demo on SQLFiddle

SQLFiddle 上的演示