代码之家  ›  专栏  ›  技术社区  ›  Tony Peterson

查找T-SQL以返回这些值

  •  1
  • Tony Peterson  · 技术社区  · 16 年前

    我正在尝试编写一个存储过程,它将根据下面的规则为每个记录返回两个计算值,但我还没有弄清楚如何构造SQL来实现它。我正在使用SQL Server 2008。

    首先,相关表和与问题相关的字段。

    生产运行

     RunID (key, and RunID is given to the stored proc as its parameter)
     ContainerName
     ProductName
     TemplateID
    

    模板测量

     MeasurementTypeID
     TemplateID
    

    简单界限

     MeasurementTypeID
     TemplateID
     UpperBound
     LowerBound
    

    遏制语言

     MeasurementTypeID
     TemplateID
     UpperBound
     LowerBound
     ContainerName
    

    产品界限

     MeasurementTypeID
     TemplateID
     UpperBound
     LowerBound
     ProductName
    

    这就是我想要回来的。我要为每个TemplateMeasurements记录返回一个计算的上限和下限值,该记录具有与具有提供的runid的ProductionRuns记录匹配的TemplateID。

    计算出的上界和下界基本上得到了最紧的界,如果它们符合条件,则可以通过简单的、容器的和产品的界得到。

    如果simplebounds记录具有正确的measurementtypeid和templateid,则该记录将成为特定measurementtypeid和templatemeasurements记录的限定界限之一。

    要使绑定到容器的记录符合条件,templateID和measurementtypeID必须匹配,但containerName也必须与productionruns记录中containerName的值匹配。同样,对于ProductBounds,这也是正确的,但对于ProductName也是如此。

    对于特定的measurementtypeid,取所有限定界限,并找到最小上界,这将是要返回的计算上界。找到限定符的最大下界,这就是返回的下界。

    但是,我不知道如何将SQL组合在一起来实现这一点。

    另外,如果三个绑定表中没有一个符合特定的measurementtypeid,则可以返回空值。

    我的想法是某种左外部联接,但我不知道如何将其扩展到三个表,这些表的结果都可能为空。

    谢谢你的帮助。

    4 回复  |  直到 16 年前
        1
  •  1
  •   Tom H zenazn    16 年前

    我现在没有时间测试这个,但希望这能让你非常接近:

    SELECT
         PR.RunID,
         PR.TemplateID,
         CASE
              WHEN MAX(SB.LowerBound) > MAX(CB.LowerBound) AND
                          MAX(SB.LowerBound) > MAX(PB.LowerBound) THEN MAX(SB.LowerBound)
              WHEN MAX(CB.LowerBound) > MAX(PB.LowerBound) THEN MAX(CB.LowerBound)
              ELSE MAX(PB.LowerBound)
         END AS LowerBound,
         CASE
              WHEN MIN(SB.UpperBound) < MIN(CB. UpperBound) AND
                          MIN(SB. UpperBound) < MIN(PB. UpperBound) THEN MIN(SB. UpperBound)
              WHEN MIN(CB. UpperBound) < MIN(PB. UpperBound) THEN MIN(CB. UpperBound)
              ELSE MIN(PB. UpperBound)
         END
    FROM
         ProductionRuns PR
    INNER JOIN TemplateMeasurements TM ON
          TM.TemplateID = PR.TemplateID
    LEFT OUTER JOIN SimpleBounds SB ON
         SB.TemplateID = PR.TemplateID AND
         SB.MeasurementTypeID = TM.MeasurementTypeID
    LEFT OUTER JOIN ContainerBounds CB ON
         CB.TemplateID = PR.TemplateID AND
         CB.MeasurementTypeID = TM.MeasurementTypeID AND
         CB.ContainerName = PR.ContainerName
    LEFT OUTER JOIN ProductBounds PB ON
         PB.TemplateID = PR.TemplateID AND
         PB.MeasurementTypeID = TM.MeasurementTypeID AND
         PB.ProductName = PR.ProductName
    GROUP BY
         PR.RunID,
         PR.TemplateID
    
        2
  •  1
  •   Welbog    16 年前

    不要忘记汤姆H的回答,但你也可以考虑用工会来解决这个问题,而不是加入工会来帮助划分不同的上/下规则。这取决于您认为将来查询需要如何更改(如果有的话)。

    查询最终看起来更干净,尤其是没有所有的事例规则,但在模板度量行不存在的情况下,它可能没有那么有用。

    SELECT RunID, TemplateID, MIN(UpperBound), MAX(LowerBound)
    FROM
    
      (SELECT PR.RunID, SB.TemplateID, SB.UpperBound, SB.LowerBound
      FROM SimpleBounds SB
      INNER JOIN TemplateMeasurements TM
          ON  SB.TemplateID = TM.TemplateID
          AND SB.MeasurementTypeID = TM.MeasurementTypeID
      INNER JOIN ProductionRuns PR
          ON  TM.TemplateID = PR.TemplateID)
    
    UNION
    
      (SELECT PR.RunID, CB.TemplateID, CB.UpperBound, CB.LowerBound
      FROM ContainerBounds CB
      INNER JOIN TemplateMeasurements TM
          ON  CB.TemplateID = TM.TemplateID
          AND CB.MeasurementTypeID = TM.MeasurementTypeID
      INNER JOIN ProductionRuns PR
          ON  TM.TemplateID = PR.TemplateID
          AND CB.ContainerName = PR.ContainerName)
    
    UNION
    
      (SELECT PR.RunID, PB.TemplateID, PB.UpperBound, PB.LowerBound
      FROM ProductBounds PB
      INNER JOIN TemplateMeasurements TM
          ON  PB.TemplateID = TM.TemplateID
          AND PB.MeasurementTypeID = TM.MeasurementTypeID
      INNER JOIN ProductionRuns PR
          ON  TM.TemplateID = PR.TemplateID
          AND PB.ProductName = PR.ProductName)
    
    GROUP BY RunID, TemplateID
    
        3
  •  1
  •   mwigdahl    16 年前

    您已经得到了其他应该有效的答案,但在我看来,这种类型的联合内部查询可以以最干净、最可维护的方式将水平层次结构折叠为垂直层次结构,这基本上是您的问题:

    SELECT MIN(iq.upperbound), MAX(iq.lowerbound)
    FROM TemplateMeasurements tm
        INNER JOIN ProductionRuns pr ON tm.TemplateID = pr.TemplateID
        LEFT JOIN
        (
        SELECT sb.UpperBound, sb.LowerBound, sb.MeasurementTypeID, '' as Name, 'sb' as Type, sb.TemplateID
        FROM SimpleBounds sb 
        UNION ALL
        SELECT cb.UpperBound, cb.LowerBound, cb.MeasurementTypeID, cb.ContainerName as Name, 'cb' as Type, cb.TemplateID
        FROM ContainerBounds cb 
        UNION ALL
        SELECT pb.UpperBound, pb.LowerBound, pb.MeasurementTypeID, pb.ProductName as Name, 'pb' as Type, pb.TemplateID
        FROM ProductBounds pb 
        ) iq ON iq.MeasurementTypeID = tm.MeasurementTypeID 
            AND iq.TemplateID = tm.TemplateID 
            AND iq.Name = 
                CASE iq.Type 
                 WHEN 'sb' THEN iq.Name 
                 WHEN 'cb' THEN pr.ContainerName 
                 WHEN 'pb' THEN pr.ProductName 
                END
        WHERE pr.RunID = @runid
        GROUP BY tm.TemplateID, tm.MeasurementTypeID
    
        4
  •  0
  •   Tony Peterson    16 年前

    谢谢你带领我走上正确的方向。在我把这个问题调整好之前,我必须先处理一段时间,但现在效果很好。

    我的最终代码和结果:

     ALTER PROCEDURE [dbo].[GetBounds]
     @runID int
     AS
     BEGIN
        SET NOCOUNT ON;
        DECLARE @templateID int
        SET @templateID = (SELECT TOP(1) TemplateID 
        FROM ProductionRuns WHERE RunID = @runID);
    
        SELECT TM.MeasurementTypeID,
    
        CASE 
        WHEN MIN(SB.UpperBound) < MIN(PB.UpperBound) 
        AND MIN(SB.UpperBound) < MIN(CB.UpperBound) THEN MIN(SB.UpperBound)
        WHEN MIN(PB.UpperBound) < MIN(SB.UpperBound) 
        AND MIN(PB.UpperBound) < MIN(CB.UpperBound) THEN MIN(PB.UpperBound)
        WHEN MIN(CB.UpperBound) < MIN(SB.UpperBound) 
        AND MIN(CB.UpperBound) < MIN(PB.UpperBound) THEN MIN(CB.UpperBound)
        ELSE MIN(SB.UpperBound) 
        END AS 'UpperBound',
    
        CASE
        WHEN MAX(SB.LowerBound) > MAX(PB.LowerBound) 
        AND MAX(SB.LowerBound) > MAX(CB.LowerBound) THEN MAX(SB.LowerBound)
        WHEN MAX(PB.LowerBound) > MAX(SB.LowerBound) 
        AND MAX(PB.LowerBound) > MAX(CB.LowerBound) THEN MAX(PB.LowerBound)
        WHEN MAX(CB.LowerBound) > MAX(SB.LowerBound) 
        AND MAX(CB.LowerBound) > MAX(PB.LowerBound) THEN MAX(CB.LowerBound)
        ELSE MAX(SB.LowerBound)
        END AS 'LowerBound'
    
        FROM
        ProductionRuns PR
        INNER JOIN TemplateMeasurements TM ON
        TM.TemplateID = PR.TemplateID
        LEFT OUTER JOIN SimpleBounds SB ON
        SB.TemplateID = PR.TemplateID AND
        SB.MeasurementTypeID = TM.MeasurementTypeID
        LEFT OUTER JOIN ContainerBounds CB ON
        CB.TemplateID = PR.TemplateID AND
        CB.MeasurementTypeID = TM.MeasurementTypeID AND
        CB.ContainerName = PR.ContainerName
        LEFT OUTER JOIN ProductBounds PB ON
        PB.TemplateID = PR.TemplateID AND
        PB.MeasurementTypeID = TM.MeasurementTypeID AND
        PB.ProductName = PR.ProductName 
    
        WHERE TM.TemplateID = @templateID
    
        GROUP BY
        TM.MeasurementTypeID
     END
    

    特定案例的部分结果,runid=3249(templateid=2)

    MeasurementTypeID   UpperBound  LowerBound
    2   NULL    NULL
    11  4   2.5
    18  30  1
    20  40  10
    33  99  0
    36  200 140
    42  120 32
    ...