web-dev-qa-db-ja.com

これらのレコード間に散在するデータとの親子関係

アプリケーションのカードに入力する60列のクエリがあります。私が直面している問題は、すべての親子関係データを子ごとに1つのレコードに収集することです。

簡単な例として:カードは、独自のテーブルを持ち、2つの重要なポイントに到達する一連のプロセスを通過します。これを、Point AおよびPoint Bと呼びます。 Card 1にヒットするPoint Aがあるとします。この時点で、カードはCard 1Card 2に分割され、Card 2の新しいレコードが作成されますが、この時点までのCard 2のデータはCard Aのレコードにあります。現在、2枚のカードは別々に処理されています。次に、Point BCard 2Card 3に分割され、Card 3の新しいレコードが作成されますが、Card 3のデータは現在Card 2Card 1にあります。そして、これは予期しない回数続く可能性があります(たとえば、Point Bで、Card 1Card 4に分割されます。

クエリ内の各カードのレコードには、次のように各レコードのデータが含まれている必要があります。

Card 1 has data from Card 1
Card 2 has data from Card 1 + Card 2
Card 3 has data from Card 1 + Card 2 + Card 3    
Card 4 has data from Card 1 + Card 4

では、問題は、再帰的なCTEがその仕事をするのでしょうか。私はそれを数回試しましたが、それを完全に機能させることができませんでした。別の方法を試す必要がありますか、それともアプリケーションでカード全体を作成するときに、各カードのデータを次のカードのレコードに複製する必要がありますか?

これがCTEでの失敗した試みでした(60あるので列の数を減らしました)

;WITH originalQry AS (

    -- create the original query here since there are LEFT JOINS
    -- this query has the 60 columns plus a bunch of tables from all
    -- the different processes      

)
,recurseCTE AS (
    SELECT 
        a.CardNumber
        ,a.ParentCardNumber
        ,a.PriorToPointAData
        ,a.PointAData
        ,a.PriorToPointBData
        ,a.PointBData
        -- 60 or so columns that show the data actually on each child record
        -- so each record is not the complete picture
    FROM 
        originalQry AS a
    WHERE 
        a.ParentCardNumber IS NOT NULL

    UNION ALL

    SELECT 
        actual.CardNumber
        ,actual.ParentCardNumber
        ,COALESCE(actual.PriorToPointAData, looper.PriorToPointAData)
        ,COALESCE(actual.PointAData, looper.PointAData)
        ,COALESCE(actual.PriorToPointBData, looper.PriorToPointBData)
        ,COALESCE(actual.PointBData, looper.PointBData)
    FROM 
        originalQry AS actual 
        INNER JOIN recurseCTE AS looper
            ON actual.CardNumber = looper.ParentCardNumber
    )

    -- try to group the records, this does not really work
    select 
        a.CardNumber
        ,a.CardNumber AS OriginalCardNumber
        ,a.ParentCardNumber
        ,MAX(COALESCE(a.PriorToPointAData,0))
        ,MAX(COALESCE(a.PointAData,0))
        ,MAX(COALESCE(a.PriorToPointBData,0))
        ,MAX(COALESCE(a.PointBData,0))
    from recurseCTE
    GROUP BY
        a.CardNumber
        ,a.CardNumber
        ,a.ParentCardNumber

更新-望ましい結果のサンプル

これはクエリが私に与えるものです

+------------+-----------+--------+--------+-----------+------+-----------+------------+------------+-------+-------+------------+-----------+----------+
| CardNumber |  Written  | Source | Design |  Started  | Qty  | PartATime | PartASpeed | PartASplit | Press | Color | PartBSplit | PartBTime | FinalQty |
+------------+-----------+--------+--------+-----------+------+-----------+------------+------------+-------+-------+------------+-----------+----------+
| A07AA      | 2/15/2015 | NA1243 | OD     | 2/16/2015 | 7.76 | 4         | 1          | ABC        | 2     | Black | AAA        |         3 |        9 |
| A07AB      | 2/15/2015 | NA1243 | OD     | 2/16/2015 | 7.76 | NULL      | NULL       | DEF        | 3     | Gray  | BBB        |         4 |        8 |
| A07AC      | 2/15/2015 | NA1243 | OD     | 2/16/2015 | 7.76 | NULL      | NULL       | NULL       | NULL  | NULL  | CCC        |         5 |        7 |
+------------+-----------+--------+--------+-----------+------+-----------+------------+------------+-------+-------+------------+-----------+----------+

これは私の望ましい結果です-あなたが見ることができるように、前のカード番号は親からの空白を埋めるだけです

   +------------+-----------+--------+--------+-----------+------+-----------+------------+------------+-------+-------+------------+-----------+----------+
| CardNumber |  Written  | Source | Design |  Started  | Qty  | PartATime | PartASpeed | PartASplit | Press | Color | PartBSplit | PartBTime | FinalQty |
+------------+-----------+--------+--------+-----------+------+-----------+------------+------------+-------+-------+------------+-----------+----------+
| A07AA      | 2/15/2015 | NA1243 | OD     | 2/16/2015 | 7.76 |         4 |          1 | ABC        |     2 | Black | AAA        |         3 |        9 |
| A07AB      | 2/15/2015 | NA1243 | OD     | 2/16/2015 | 7.76 |         4 |          1 | DEF        |     3 | Gray  | BBB        |         4 |        8 |
| A07AC      | 2/15/2015 | NA1243 | OD     | 2/16/2015 | 7.76 |         4 |          1 | DEF        |     3 | Gray  | CCC        |         5 |        7 |
+------------+-----------+--------+--------+-----------+------+-----------+------------+------------+-------+-------+------------+-----------+----------+
1
jmzagorski

ですから、もう少し考えていくつかの投稿を読んだ後、クエリを2つの部分に分割しました。可動部分が非常に多かったため、それが主な混乱だったと思います。

  1. ターゲットテーブルで再帰を実行するビューを作成し(以下を参照)、それによって他の列が不要になりました
  2. このテーブルを60列のクエリで使用しました。

これが、最終的に機能するようになった再帰です。私の問題の一部は、最終結果でその親とすべての子が必要だったということでした。 OPTION(MAXRECURSION 676)を設定しました。これは、さらに調査した後に実行できることが最も多いためです。

WITH recursion AS (

    SELECT 
        CardNumber
        ,CardNumber AS ParentSerialNumber
    FROM 
        dbo.Card

    UNION ALL

    SELECT 
      p.CardNumber
      ,c.ParentSerialNumber
    FROM 
        recursion AS c
        INNER JOIN  dbo.Card AS p
            ON p.ParentSerialNumber = c.SerialNumber
)

SELECT 
        SerialNumber
        ,ParentSerialNumber
FROM
    recursion
1
jmzagorski