1

私は現在2つのテーブルを扱っています。

1 つのテーブルには、ID、NAME、AGE、TEAM、SCHOOL などの一連の列が PRIMARY_TABLE というテーブルに含まれています。

また、前述の値の経時的な更新を記録する SECONDARY_TABLE という監査テーブルもあります。

このテーブルには、ATTRIBUTE、PREV_VALUES、および RECORD_ID 列があります。次の属性があります。

  • RECORD_ID 列は PRIMARY_TABLE の ID 列に対応します
  • ATTRIBUTE 列には、変更される PRIMARY_TABLE の列が格納されます。

たとえば、私が持っている場合

132 NIKO 18 LANCERS JESUIT
143 KEENAN 25 RAIDERS ROCKLAND 

私の最初のテーブルで

132 'AGE' 22
132 'NAME' STEVAN 

私の2番目に、

次に、結合されたテーブルが必要です

132 NIKO 18 LANCERS JESUIT
132 NIKO 22 LANCERS JESUIT
132 STEVAN 22 LANCERS JESUIT
143 KEENAN 25 RAIDERS ROCKLAND .

私が回避するのに苦労している問題は、影響を受けていない行の値を保持することです。このため、2 つのテーブルを結合するという考えはうまくいかないようです。

何かご意見は?唯一の解決策は、このためのストアド プロシージャを作成することだと思います。説明が必要な場合は、私にもお知らせください。

編集

もう一つ...

ここに別のことがあります。監査テーブルには、「time_of_change」列もあります。複数の行で ID の変更時刻が同じである場合、結果のテーブルに複数の行が含まれる代わりに、もう 1 行だけ存在する必要があります。

たとえば、監査テーブルに

132 'AGE' 22 1:00
132 'NAME' STEVAN 1:00

次に、持つ代わりに

132 STEVAN 18 LANCERS JESUIT
132 NIKO   22 LANCERS JESUIT

が追加された場合、追加されるのは の行が 1 つだけである必要があり 132 STEVAN 22 LANCERS JESUITます。

これを行う方法も考えられません。

4

3 に答える 3

3

UPDATE2 secondary_tableに更新日時の列がある場合 (これを と呼びupdated_atましょう)、結果セットを適切に並べ替えることができます。

SELECT id, name, age, team, school, GETDATE() updated_at 
  FROM primary_table
UNION ALL
SELECT p.id, 
       CASE WHEN s.attribute = 'NAME'   
            THEN s.prev_values ELSE p.name END name,
       CASE WHEN s.attribute = 'AGE'    
            THEN s.prev_values ELSE p.age END age, 
       CASE WHEN s.attribute = 'TEAM'   
            THEN s.prev_values ELSE p.team END team, 
       CASE WHEN s.attribute = 'SCHOOL' 
            THEN s.prev_values ELSE p.school END school,
       updated_at
  FROM primary_table p JOIN secondary_table s
    ON p.ID = s.record_id
ORDER BY id, updated_at DESC

これがSQLFiddleのデモです

UPDATE1 1 つのバージョンUNIONと条件付き出力CASE

SELECT * 
  FROM primary_table
UNION ALL
SELECT p.id, 
       CASE WHEN s.attribute = 'NAME'   
            THEN s.prev_values ELSE p.name END name,
       CASE WHEN s.attribute = 'AGE'    
            THEN s.prev_values ELSE p.age END age, 
       CASE WHEN s.attribute = 'TEAM'   
            THEN s.prev_values ELSE p.team END team, 
       CASE WHEN s.attribute = 'SCHOOL' 
            THEN s.prev_values ELSE p.school END school
  FROM primary_table p JOIN secondary_table s
    ON p.ID = s.record_id
ORDER BY id

これがSQLFiddleのデモです

UNIONs付きのオリジナルバージョン

SELECT * 
  FROM primary_table
UNION ALL
SELECT p.id, s.prev_values, p.age, p.team, p.school
  FROM primary_table p JOIN secondary_table s
    ON p.ID = s.record_id
   AND s.attribute = 'NAME'
UNION ALL
SELECT p.id, p.name, s.prev_values, p.team, p.school
  FROM primary_table p JOIN secondary_table s
    ON p.ID = s.record_id
   AND s.attribute = 'AGE'
ORDER BY id

出力:

|  ID |   NAME | AGE |    TEAM |   SCHOOL |
-------------------------------------------
| 132 |   NIKO |  18 | LANCERS |   JESUIT |
| 132 | STEVAN |  18 | LANCERS |   JESUIT |
| 132 |   NIKO |  22 | LANCERS |   JESUIT |
| 143 | KEENAN |  25 | RAIDERS | ROCKLAND |

これがSQLFiddleのデモです

于 2013-06-03T05:53:24.577 に答える
0

開始するためのスクリプトを次に示します。あなたの前には大きな仕事があります。監査テーブルに現在の値がない場合、事態はかなり難しくなります (そのように思われるため、その前提でスクリプトを作成しました)。

WITH Curr AS (
   SELECT
      Record_ID = T.ID,
      V.*,
      Time_Of_Change = Convert(datetime, 0)
   FROM
      dbo.Team T
      CROSS APPLY (VALUES
         ('Name', Convert(varchar(20), T.Name)),
         ('Age', Convert(varchar(20), T.Age)),
         ('Team', Convert(varchar(20), T.Team)),
         ('School', Convert(varchar(20), T.School))
      ) V (Attribute, Prev_Values)
),
Data AS (
   SELECT
      H.Record_ID,
      H.Time_Of_Change,
      C.Attribute,
      A.Prev_Values
   FROM
      (
         SELECT DISTINCT Record_ID, Time_Of_Change
         FROM dbo.Audit
         WHERE TableName = 'Team'
         UNION ALL
         SELECT DISTINCT ID, GetDate()
         FROM dbo.Team
      ) H
      CROSS JOIN (VALUES
         ('Name'), ('Age'), ('Team'), ('School')
      ) C (Attribute)
      CROSS APPLY (
         SELECT TOP 1 *
            FROM (
              SELECT Record_ID, Attribute, Prev_Values, Time_Of_Change
              FROM dbo.Audit
              WHERE TableName = 'Team'
              UNION ALL
              SELECT *
              FROM Curr
           ) A
         WHERE
            H.Record_ID = A.Record_ID
            AND H.Time_Of_Change >= A.Time_Of_Change
            AND C.Attribute = A.Attribute
         ORDER BY
            A.Time_Of_Change DESC
      ) A
)
SELECT *
FROM
   Data
   PIVOT (Max(Prev_Values) FOR Attribute IN (Name, Age, Team, School)) P
;

SQL Fiddle でライブ デモを見る

履歴を再構築する各テーブルのビューを非常に簡単に作成できます。ビューを照会するストアド プロシージャをINFORMATION_SCHEMA.COLUMNS構築し、私が提供したものと同様のものを構築します。テーブルの変更後に SP を 1 回実行すると、ビューが更新されます。

私のスクリプトが正しくないことに気付きました。編集用に 3 行ではなく 2 行が表示されています。さらに、監査行がない行には有効な時間がありません。しかし、その部分は理にかなっています。いずれにせよ、あなたの前には大きな仕事があります...

于 2013-06-04T00:34:03.853 に答える
0

これは完璧ではありませんが、これを試してください:

SELECT * FROM Primary_Table
UNION ALL
SELECT * FROM
(SELECT A.ID, A.Name, B.GetAge as Age, A.School
 FROM Primary_Table A INNER JOIN (SELECT Record_id, CONVERT(int,Value) as GetAge FROM    Secondary_Table
 WHERE Attrib='AGE'  ) B
 ON A.ID = B.Record_id) UAge
 UNION ALL
SELECT * FROM
(SELECT A.ID, B.GetName as Name, A.Age, A.School
FROM Primary_Table A INNER JOIN (SELECT Record_id, Value as GetName FROM    Secondary_Table
WHERE Attrib='NAME'  ) B
ON A.ID = B.Record_id) UName
ORDER BY ID
于 2013-06-03T06:08:55.980 に答える