1

好的,这里是故事:我为一家公司工作,该公司将有害液体化学品回收成有用的化学品。这一过程的一部分涉及将这些材料从一个罐移到另一个罐,因为回收过程的每个部分都已完成。这些坦克要么在我们的坦克农场,在蒸馏系统的一部分,在有轨电车,或油罐卡车。我分配的任务是写一个查询,让经理拿起任何坦克,并跟随该材料通过每个坦克的运动,直到它被处置或出售。这个数据库大概是在10年前建立起来的,所以我只需要处理数据(即不能改变数据库使其更容易处理)。递归T-SQL查询使用日期和坦克名称

查阅表的结构:即适合这种努力中列有:

  • SouceTank
  • Opendate里(这一天空罐开始接收材料)
  • CosedDate(罐是日期关闭,清空,并准备好新的材料)
  • DestinationTank(坦克的材料被移动到)
  • ProductName(我添加这个验证动作。许多材料不能混合。有些是。如果算法运行不正常,那么不能混合的问题就会出现问题。)

所有的坦克都会有OpenDate但坦克仍然被装满或者等待运出不会有关闭日期。大多数情况下,坦克是化学不可知的 - 因为任何空罐都可以用于任何化学品。任何地方都可以预计1到10次动作。

我试过使用递归CTE T-SQL算法,但很快就迷路了,试图将SourceTank与匹配的DestinationTank匹配,SourceTank的CosedDate位于DestinationTank的OpenDate和CosedDate之间,或者至少等于或等于DestinationTank的OpenDate如果尚未关闭。

的样本数据:

SourceTank StartDate ClosedDate DestinationTank ProductName 
------------------------------------------------------------------------ 
TNK01-5  08/03/2017 08/10/2017 TNK30-6   Fuels 
TNK01-5  08/07/2017 08/10/2017 TNK40-6   Fuels 
TNK01-5  07/20/2017 07/31/2017 TNK01-5   Incin 
TNK01-5  08/10/2017 08/17/2017 TNK30-6   Incin 
TNK01-5  08/12/2017 08/17/2017 TNK30-6   Fuels 
TNK03-5  08/13/2017 08/22/2017 TNK30-6   IBAC feed 
TNK07-5  08/11/2017 08/17/2017 TNK40-6   Incin 
TNK07-5  08/14/2017 08/29/2017 TNK40-6   Fuels 
TNK07-5  07/15/2017 08/10/2017 TNK30-6   Picoline Cut 
TNK07-5  08/03/2017 08/10/2017 TNK02-5   Pico 2nd Pass 
TNK07-5  08/06/2017 08/17/2017 TNK40-6   Fuels 
TNK08-5  08/05/2017 08/10/2017 TNK40-6   Fuels 
TNK08-5  08/07/2017 08/08/2017 TNK30-6   Fuels 
TNK08-5  08/10/2017 08/22/2017 TNK40-6   Water 
TNK08-5  07/24/2017 08/10/2017 TNK02-5   Picoline Cut 
TNK09-10 07/20/2017 NULL   TNK30-6   Picoline Crude 
TNK09-10 07/21/2017 08/04/2017 TNK30-6   Picoline Crude 
TNK09-10 08/02/2017 08/10/2017 TNK30-6   Cyclo Waste 
TNK09-10 08/05/2017 08/10/2017 TNK30-6   Cyclo Waste 
TNK09-10 08/07/2017 08/10/2017 TNK30-6   Cyclo Waste 
TNK09-10 08/04/2017 08/10/2017 TNK30-6   Cyclo Waste 
TNK09-10 08/15/2017 08/22/2017 TNK30-6   IBAC feed 
TNK09-10 08/11/2017 08/17/2017 TNK30-6   IBAC feed 
TNK09-10 08/12/2017 08/17/2017 TNK30-6   IBAC feed 
TNK30-6  08/08/2017 08/29/2017 TNK30-6   Cyclo Waste 
TNK40-6  08/13/2017 08/22/2017 TNK30-6   IBAC:PRODUCT 
TNK41-6  08/14/2017 09/27/2017 NATX25496   IBAC:PRODUCT 
TNK51-12 07/26/2017 09/15/2017 TNK30-6   CYCLO Product 
TNK62-12 07/28/2017 09/12/2017 TNK30-6   NON-RCRA NMP 
TNK74-12 07/29/2017 NULL   TNK30-6   Picoline Crude 
TNK91-8  08/03/2017 08/22/2017 TNK08-5   Picoline Prod 

这里是我的尝试。不知道如何处理NULL ClosingDate ..

WITH TanksCTE AS (
SELECT [TrackingNum] 
     ,[TblTankTracking].[TankID] 
     ,[StartDate] 
     ,[TblTankTracking].[ProductID] 
     ,[ClosedDate] 
     ,[Destination] 
    FROM [MAFTS].[Laboratory].[TblTankTracking] 

UNION ALL 

SELECT TCTE.[TrackingNum] 
     ,TRACK.[TankID] 
     ,TRACK.[StartDate] 
     ,TRACK.[ProductID] 
     ,TRACK.[ClosedDate] 
     ,TRACK.[Destination] 
    FROM TanksCTE AS TCTE INNER JOIN 
     [MAFTS].[Laboratory].[TblTankTracking] TRACK 
     ON TCTE.[TankID] = TRACK.[Destination] 
     AND TRACK.[ClosedDate] BETWEEN TCTE.[StartDate] AND TCTE.[ClosedDate] 
) 

SELECT * FROM TanksCTE 
    option (maxrecursion 0) 
+0

请与我们分享您的输入参数是什么(如果有的话)。你只是想在坦克的基础上做这个查询),以及你的预期输出应该是什么。如果您已经开始了一个不适用的查询,那么这个查询可能也很有用。 – pcdev

+0

请阅读[this](http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/)了解一些关于改善问题的提示。使用适当的软件(MySQL,Oracle,DB2,...)和版本(例如, '的SQL服务器2014'。语法和功能的差异往往会影响答案。请注意,'tsql'缩小了选择范围,但不指定数据库。 – HABO

+0

什么是正确的结果?虽然我们可以产生各种查询,但最好能通过提供的数据知道您期望的结果)。 *它还使我们能够验证我们建议的任何查询,所以减少对您的查询。* –

回答

1

我不知道这是多么有用将是因为我不知道预期的结果应该是什么样子,但它可能帮助。我试图理解日期,这就是为什么你会看到它们连接成一个通路列。我也不确定从哪里开始,所以我猜测每个坦克的最早开始时间。

SQL Fiddle

的MS SQL Server 2014架构设置

CREATE TABLE Table1 
    ([SourceTank] varchar(8), [StartDate] datetime, [ClosedDate] datetime, [DestinationTank] varchar(9), [ProductName] varchar(14)) 
; 

INSERT INTO Table1 
    ([SourceTank], [StartDate], [ClosedDate], [DestinationTank], [ProductName]) 
VALUES 
    ('TNK01-5', '2017-08-03 00:00:00', '08/10/2017', 'TNK30-6', 'Fuels'), 
    ('TNK01-5', '2017-08-07 00:00:00', '08/10/2017', 'TNK40-6', 'Fuels'), 
    ('TNK01-5', '2017-07-20 00:00:00', '07/31/2017', 'TNK01-5', 'Incin'), 
    ('TNK01-5', '2017-08-10 00:00:00', '08/17/2017', 'TNK30-6', 'Incin'), 
    ('TNK01-5', '2017-08-12 00:00:00', '08/17/2017', 'TNK30-6', 'Fuels'), 
    ('TNK03-5', '2017-08-13 00:00:00', '08/22/2017', 'TNK30-6', 'IBAC feed'), 
    ('TNK07-5', '2017-08-11 00:00:00', '08/17/2017', 'TNK40-6', 'Incin'), 
    ('TNK07-5', '2017-08-14 00:00:00', '08/29/2017', 'TNK40-6', 'Fuels'), 
    ('TNK07-5', '2017-07-15 00:00:00', '08/10/2017', 'TNK30-6', 'Picoline Cut'), 
    ('TNK07-5', '2017-08-03 00:00:00', '08/10/2017', 'TNK02-5', 'Pico 2nd Pass'), 
    ('TNK07-5', '2017-08-06 00:00:00', '08/17/2017', 'TNK40-6', 'Fuels'), 
    ('TNK08-5', '2017-08-05 00:00:00', '08/10/2017', 'TNK40-6', 'Fuels'), 
    ('TNK08-5', '2017-08-07 00:00:00', '08/08/2017', 'TNK30-6', 'Fuels'), 
    ('TNK08-5', '2017-08-10 00:00:00', '08/22/2017', 'TNK40-6', 'Water'), 
    ('TNK08-5', '2017-07-24 00:00:00', '08/10/2017', 'TNK02-5', 'Picoline Cut'), 
    ('TNK09-10', '2017-07-20 00:00:00', NULL, 'TNK30-6', 'Picoline Crude'), 
    ('TNK09-10', '2017-07-21 00:00:00', '08/04/2017', 'TNK30-6', 'Picoline Crude'), 
    ('TNK09-10', '2017-08-02 00:00:00', '08/10/2017', 'TNK30-6', 'Cyclo Waste'), 
    ('TNK09-10', '2017-08-05 00:00:00', '08/10/2017', 'TNK30-6', 'Cyclo Waste'), 
    ('TNK09-10', '2017-08-07 00:00:00', '08/10/2017', 'TNK30-6', 'Cyclo Waste'), 
    ('TNK09-10', '2017-08-04 00:00:00', '08/10/2017', 'TNK30-6', 'Cyclo Waste'), 
    ('TNK09-10', '2017-08-15 00:00:00', '08/22/2017', 'TNK30-6', 'IBAC feed'), 
    ('TNK09-10', '2017-08-11 00:00:00', '08/17/2017', 'TNK30-6', 'IBAC feed'), 
    ('TNK09-10', '2017-08-12 00:00:00', '08/17/2017', 'TNK30-6', 'IBAC feed'), 
    ('TNK30-6', '2017-08-08 00:00:00', '08/29/2017', 'TNK30-6', 'Cyclo Waste'), 
    ('TNK40-6', '2017-08-13 00:00:00', '08/22/2017', 'TNK30-6', 'IBAC:PRODUCT'), 
    ('TNK41-6', '2017-08-14 00:00:00', '09/27/2017', 'NATX25496', 'IBAC:PRODUCT'), 
    ('TNK51-12', '2017-07-26 00:00:00', '09/15/2017', 'TNK30-6', 'CYCLO Product'), 
    ('TNK62-12', '2017-07-28 00:00:00', '09/12/2017', 'TNK30-6', 'NON-RCRA NMP'), 
    ('TNK74-12', '2017-07-29 00:00:00', NULL, 'TNK30-6', 'Picoline Crude'), 
    ('TNK91-8', '2017-08-03 00:00:00', '08/22/2017', 'TNK08-5', 'Picoline Prod') 
; 

查询1

with TankStart as (
    select 
      * 
     , row_number() over(partition by SourceTank order by StartDate ASC) as rn 
    from Table1 
    ) 
, TankPaths as (
     SELECT 
      T.SourceTank 
      , T.DestinationTank 
      , T.StartDate 
      , T.ClosedDate 
      , T.ProductName 
      , CAST(T.DestinationTank AS varchar(max)) 
      + ' ' 
      + convert(varchar(10),T.ClosedDate,120) 
      AS Pathway 
     FROM TankStart T 
     WHERE T.rn = 1 
     union all 
     SELECT 
      T1.SourceTank 
      , T1.DestinationTank 
      , T1.StartDate 
      , T1.ClosedDate 
      , T1.ProductName 
      , M.Pathway 
      + ' ' 
      + convert(varchar(10),T1.StartDate,120) 
      + ', ' 
      + CAST(T1.DestinationTank AS varchar(max)) 
      + ', ' 
      + convert(varchar(10),T1.ClosedDate,120) 

     FROM Table1 T1 
     INNER JOIN TankPaths M ON M.DestinationTank = T1.SourceTank 
         AND M.ClosedDate <= T1.StartDate 
     where T1.SourceTank <> T1.DestinationTank 
    ) 
select * 
from TankPaths 
order by 1, 2, Pathway 

Results

| SourceTank | DestinationTank |   StartDate |   ClosedDate | ProductName |                   Pathway | 
|------------|-----------------|----------------------|----------------------|----------------|------------------------------------------------------------------------------------| 
| TNK01-5 |   TNK01-5 | 2017-07-20T00:00:00Z | 2017-07-31T00:00:00Z |   Incin |                 TNK01-5 2017-07-31 | 
| TNK01-5 |   TNK30-6 | 2017-08-03T00:00:00Z | 2017-08-10T00:00:00Z |   Fuels |         TNK01-5 2017-07-31 2017-08-03, TNK30-6, 2017-08-10 | 
| TNK01-5 |   TNK30-6 | 2017-08-10T00:00:00Z | 2017-08-17T00:00:00Z |   Incin |         TNK01-5 2017-07-31 2017-08-10, TNK30-6, 2017-08-17 | 
| TNK01-5 |   TNK30-6 | 2017-08-12T00:00:00Z | 2017-08-17T00:00:00Z |   Fuels |         TNK01-5 2017-07-31 2017-08-12, TNK30-6, 2017-08-17 | 
| TNK01-5 |   TNK40-6 | 2017-08-07T00:00:00Z | 2017-08-10T00:00:00Z |   Fuels |         TNK01-5 2017-07-31 2017-08-07, TNK40-6, 2017-08-10 | 
| TNK03-5 |   TNK30-6 | 2017-08-13T00:00:00Z | 2017-08-22T00:00:00Z |  IBAC feed |                 TNK30-6 2017-08-22 | 
| TNK07-5 |   TNK30-6 | 2017-07-15T00:00:00Z | 2017-08-10T00:00:00Z | Picoline Cut |                 TNK30-6 2017-08-10 | 
| TNK08-5 |   TNK02-5 | 2017-07-24T00:00:00Z | 2017-08-10T00:00:00Z | Picoline Cut |                 TNK02-5 2017-08-10 | 
| TNK09-10 |   TNK30-6 | 2017-07-20T00:00:00Z |    (null) | Picoline Crude |                    (null) | 
| TNK30-6 |   TNK30-6 | 2017-08-08T00:00:00Z | 2017-08-29T00:00:00Z | Cyclo Waste |                 TNK30-6 2017-08-29 | 
| TNK40-6 |   TNK30-6 | 2017-08-13T00:00:00Z | 2017-08-22T00:00:00Z | IBAC:PRODUCT | TNK01-5 2017-07-31 2017-08-07, TNK40-6, 2017-08-10 2017-08-13, TNK30-6, 2017-08-22 | 
| TNK40-6 |   TNK30-6 | 2017-08-13T00:00:00Z | 2017-08-22T00:00:00Z | IBAC:PRODUCT |                 TNK30-6 2017-08-22 | 
| TNK41-6 |  NATX25496 | 2017-08-14T00:00:00Z | 2017-09-27T00:00:00Z | IBAC:PRODUCT |                NATX25496 2017-09-27 | 
| TNK51-12 |   TNK30-6 | 2017-07-26T00:00:00Z | 2017-09-15T00:00:00Z | CYCLO Product |                 TNK30-6 2017-09-15 | 
| TNK62-12 |   TNK30-6 | 2017-07-28T00:00:00Z | 2017-09-12T00:00:00Z | NON-RCRA NMP |                 TNK30-6 2017-09-12 | 
| TNK74-12 |   TNK30-6 | 2017-07-29T00:00:00Z |    (null) | Picoline Crude |                    (null) | 
| TNK91-8 |   TNK08-5 | 2017-08-03T00:00:00Z | 2017-08-22T00:00:00Z | Picoline Prod |                 TNK08-5 2017-08-22 | 
+0

我喜欢这个解决方案。我将不得不研究一下,看看它是否能为我们完成这项工作。 –

+0

用户可以从任何坦克开始,也可以在此过程的任何阶段开始。所以,他/她可能会在中间的某个地方找到材料从那里出发的地方。 –

+0

未来的访问者会知道,我将采用@Used_By_Already提供的这个框架,并添加与每个传输相关的信息,以使其对我们的管理更加有用。谢谢Used_By_Already! –