【问题标题】:how to loop through table2 with column value in table 1如何使用表 1 中的列值遍历表 2
【发布时间】:2018-10-09 00:52:53
【问题描述】:

我有两张表,表 1 和表 2。

Table1 :
ID   Type   StartDate    EndDate   Units
AAA  1      4/3/2018     4/7/2018   1
AAA  1      4/8/2018     4/21/2018  1
AAA  1      1/8/2017     2/6/2017   2
AAA  1      1/1/2017     1/7/2017   2
BBB  2      7/16/2017    7/22/2017  1 
BBB  2      8/1/2017     8/1/2017   1

Table 2:
  ID   Type   StartDate     EndDate 
 AAA   1      01/02/2017    01/17/2017
 AAA   1      01/02/2017    01/17/2017
 AAA   1      01/02/2017    01/17/2017
 AAA   1      01/02/2017    01/17/2017
 AAA   1      02/01/2017    02/28/2017
 AAA   1      02/01/2017    02/28/2017
 AAA   1      02/01/2017    02/28/2017
 AAA   1      02/01/2017    02/28/2017
 AAA   1      02/01/2017    02/28/2017
 AAA   1      04/03/2018    04/03/2018
 AAA   1      04/10/2018    04/10/2018
 BBB   2      07/20/2017    07/21/2017
 BBB   2      08/01/2017    09/01/2017

我必须查看 (table2. Startdate between Table1 start date and end date) 或 (table2 enddate between table1 start date and end date) 并循环标记 Table2 =Y 以获取该范围内 table1 中的单元数。

My Expected output is :
ID   Type   StartDate     EndDate        Flag
 AAA   1      01/02/2017    01/17/2017   Y 
 AAA   1      01/02/2017    01/17/2017   Y
 AAA   1      01/02/2017    01/17/2017   Y 
 AAA   1      01/02/2017    01/17/2017   Y
 AAA   1      02/01/2017    02/28/2017   N
 AAA   1      02/01/2017    02/28/2017   N
 AAA   1      02/01/2017    02/28/2017   N 
 AAA   1      02/01/2017    02/28/2017   N
 AAA   1      02/01/2017    02/28/2017   N
 AAA   1      04/03/2018    04/03/2018   Y 
 AAA   1      04/10/2018    04/10/2018   Y
 BBB   2      07/20/2017    07/21/2017   Y
 BBB   2      08/01/2017    09/01/2017   Y

我必须考虑这两个表的 ID、类型和日期范围。我必须检查表 2 和表 1 的表 2 开始日期和表 2 结束日期。 谁能帮我解决这个循环?

这里是这个的代码。

SELECT ROW_NUMBER() OVER(
ORDER BY id, StartDate, EndDate) AS AID, StartDate
id , units, StartDate, EndDate, [Type], Flag
INTO #tempA
FROM #table1;

SELECT ROW_NUMBER() OVER( ORDER BY ID, StartDate, EndDate, Type,Flag) AS CID,
 ID, StartDate, EndDate, Type, Flag
INTO #tempC
FROM #table2;


    SELECT a.AID
         , c.CID
         , a.ID
    INTO #tempCombined
    FROM
         #tempA a CROSS JOIN #tempC c
    WHERE a.ID = c.ID
          AND a.Type = c.Type
          AND ((c.StartDate BETWEEN a.StartDate AND a.EndDate) 
               OR (c.EndDate BETWEEN a.StartDate AND a.EndDate))
    ORDER BY a.Aid , c.CID

DECLARE @List TABLE
    (
         Aid    INT, 
         Cid    INT, 
         ID Varchar(50)
    )

DECLARE @count INT, @countMax INT, @Unit INT

SET @count = 1

SELECT @countMax = MAX(aid)
FROM #tempA

-- get @List which CIDs to be proved
WHILE @count <=  @countMax
    BEGIN

        SELECT @Unit = units
        FROM #tempA
        WHERE aid = @count

        SET ROWCOUNT @Unit

        INSERT INTO @List (Aid , Cid , ID)
           SELECT ac.AID , ac.CID , ac.ID
           FROM #tempCombined ac 
           WHERE ac.AID = @count 
                 AND ac.CID not in (select cid from @List where ID=ac.ID)
        order by cid,ID
        SET ROWCOUNT 0
        SET @count+=1
    END

UPDATE c
  SET 
      c.UpdateFlag = 'Y'
FROM #tempC c 
INNER JOIN @List cl
ON c.CID = cl.Cid

SELECT *
FROM #tempC

【问题讨论】:

  • 不要。在 sql 中循环是邪恶的,请改用 join。
  • 是的.. 但我不知道除此之外的任何其他方法。相反,我们可以使用 SSIS 包来做到这一点吗?

标签: sql sql-server sql-server-2016


【解决方案1】:

你不需要循环,只需要正确的连接。

select 
   t2.*
   ,Flag = case when t1.Units is not null then 'Y' else 'N' end --or whatever logic
from Table2 t2
left join Table1 t1 on 
    t1.ID = t2.ID
and t1.Type = t2.Type
and(
       (t2.StartDate between t1.StartDate and t1.EndDate) 
    or (t2.EndDate between t1.Startdate and t1.EndDate)
   )

【讨论】:

  • 所有记录均为 Y。对于 ID AA0160000000000,在第一个日期范围内(它们重叠)中只有 4 行应标记为 Y,而在另一个日期范围内每行标记为 1 个单位
  • 该 ID 不在您的数据中,所以我不知道您的意思,但也许您描述的逻辑不正确或不完整
  • AAA 1 02/01/2017 02/28/2017 NFlag = N 当它是开始日期时,02/01/2017 是在表 1 中的开始日期和结束日期之间,即 1/8/2017 2/6/2017?您明确表示您的问题应该是这种情况。 我要看看 (table2.startdate between Table1 start date and end date) or (table2 enddate between table1 start date and end date)
  • 是的。所以 AAA 在同一日期范围内有 9 行和 2 行(它们是重叠的)但是,表 1 中的 AAA 在这个日期范围内的单位是 2 个单位,每个单位是 4 个单位。现在我们需要将表 2 中 9 行中的 4 行标记为 Y,其余为 N。
  • 这毫无意义。 AAA 有 11 行,超过 4 个日期范围。其中 2 行具有相同的开始日期和结束日期。这不是你刚才说的。无论如何,我不明白你其余的评论是什么意思,祝你好运。我编写的代码完全符合您的要求,但您所要求的并没有产生您预期的结果,我看不出有任何逻辑。
【解决方案2】:

一种方法是逐行遍历表 2,然后将其与表 1 进行比较。除非表很小,否则此方法可能存在性能问题。

CREATE TABLE T4
([ID] varchar(3), [Type] int, [StartDate] datetime, [EndDate] datetime, [Flag] varchar(1))
; 
WHILE (SELECT count(*) FROM t2) > 0
BEGIN   
   select top(1) * into t3 from t1 where (((select top(1) startDate from t2) between t1.startDate and t1.endDate)  or ((select top(1) endDate from t2) between t1.startDate and t1.endDate)) and t1.units>0
   IF (select count(*) from t3) > 0
       insert into t4 ([ID] , [Type] , [StartDate] , [EndDate] , [Flag]) (select top(1) *,Flag='Y' from t2);
   ELSE
       insert into t4 ([ID] , [Type] , [StartDate] , [EndDate] , [Flag]) (select top(1) *,Flag='N' from t2);
   delete top(1) from t2;
   update t1 set units = units-1 where t1.startDate=(select startdate from t3) and t1.endDate=(select enddate from t3) and t1.type=(select type from t3) and t1.id=(select id from t3);
   drop table t3;
END

【讨论】:

  • 非常感谢您的帮助。我会试试表演。
猜你喜欢
  • 2021-02-16
  • 1970-01-01
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-31
  • 2019-02-14
  • 1970-01-01
相关资源
最近更新 更多