2011-08-03 8 views
2

現在正規化されていないMS Accessデータベースを書き直し中で、設計が非常にうまくいかない。この再設計の私の問題は、テーブル間で日々データを移動する方法を取り巻くものです。SQLサーバで既存のMS Accessテーブルを再設計する方法

現在の設定はこれに似ています。私はテーブルに読み込まれるテキストファイルを持っています。必要なレコードがTable1に追加され、翌日にはTable1のデータの一部がTable2にロードされます。 Table2は、その日のインポート後にTable1を更新するために使用されます。ファイルには、表1を更新し、フィールドに6/2/11に

6/2/11 
Step 1     Step 2    Step 3 
Table1 > Table2   File > Table1  Table2 > Table1 
field1 field1     newdata1  field1 newdata1 
field2 field2     newdata2  field2 newdata2 

に移入されます6/1/11で

6/1/11 
File > Table1 
     field1 
     field2 

、最初のステップは、フィールド1 /フィールド2 GETはtable2のに移動していることである(A一時テーブル)。次に、table1からデータを削除し、ステップ2でその日からファイルをインポートします。ステップ3では、account2が存在する場合、table2のデータを使用してtable1の更新を実行します。基本的には、アカウントが存在すれば、今日のデータを昨日のデータに転送しています。

私の新しいデザインでは、私はこのようなテーブルを持っています。テーブルのプライマリキーは、BusinessDateとAccountとなります。なぜなら、これらのキーは毎日異なるからです。

CREATE TABLE [dbo].[Table](
    [BusinessDate] [smalldatetime] NOT NULL, 
    [Account] [int] NOT NULL, 
    [Guid] [uniqueidentifier] NOT NULL, 
    [InitialAmount] [money] NULL, 
    [LetterDate] [smalldatetime] NULL, 
    [LetterType] [varchar](50) NULL, 
    [Status] [varchar](50) NULL, 
    [Reason] [varchar](50) NULL, 
    [FollowUpDate] [smalldatetime] NULL, 
    [LastModifiedBy] [varchar](50) NULL, 
    [LastModifiedDate] [datetime] NULL 
) ON [PRIMARY] 

アカウントが追加された場合6/1、その後は、私は上記のフィールドに6/1からのデータを使用して更新を行うことになる6/2にインポートしました。私は毎日このような種類のコピーデータを続けていくことは悪い設計であると言われています。しかし、私は日々の記録が新しいと考えられるので、これをどのように実装するのか分かりませんが、元のデータニーズのいくつかは将来のすべての項目に付随しています。

このタイプのセットアップは現在の設定全体で使用されており、私はそれをどのように設計するのか困惑しています。誰もがこのデザインを進める方法に関する提案を提供できますか?これは説明が難しいので、明確でない場合はお尋ねください。

EDIT:私の問題の

パートは私が任意の日のために前方に移動します詳細情報にアクセスできるようにする必要があるということです。アカウントに初期金額の8/1/11に入っているアカウントがある場合、ユーザーはステータス、文字タイプを割り当てます。そして同じアカウントが8/2/11に来たら、8/2の出発点は8/1の終わりの値です。彼らはその日のアカウントを処理します。アカウントは8/2に開始されますが、何もせずに昨日の値から開始します。

ユーザーは、8/1のデータにアクセスして終了日の値を確認する必要があります。

例:

  • 8/1/11アカウント1234567890はの借方に追加されます - 見直し=担当者がステータスを割り当て、$ 10の理由=問題をチェック
  • 8/2/11アカウント1234567890取得します
  • 8/2/11 - ユーザーは口座1234567890のデータを借方$ -50で処理し、ステータス=解決済み、理由=なしを変更しました
  • 8/3/11 - ユーザーが1234567890のアカウントの営業日8/1/11の検索を実行するeステータス=レビューあり、理由=チェック問題あり

詳細情報が役立ちますように。非常に長い説明を申し訳ありません。

+0

あなたといくつかのことを確認したいだけです。 - この「コピーフォワード」を使用する必要がないようにデザインを簡素化しようとしていますか? - Table1の終了状態は、既に存在するレコードのTable2のデータと、存在しないレコードのTable2のデータが含まれていることです。 –

+0

はい、それは理想的なセットアップですが、私はそれを可能にする方法がわかりません。ユーザーは、レコードがテーブル内にある毎日のデータを検索できる必要があります。さらに、各レコードの残高は毎日違っており、それを見ることができる必要があります。 – Taryn

+0

わかりましたので、私の理解を要約しましょう。Table1には今日のデータが含まれ、Table2には前日のすべてのデータが含まれています。すべてのアカウントの詳細が含まれているファイルを毎日(他のシステムから推測していますが)毎日作成していますか?毎日、Table1はあなたの履歴Table2に移動され、Table1はファイルの内容に置き換えられ、そのデータはTable2のデータによって上書きされますか?それが正しいとすれば、今日のTable1のデータとTable2のデータの昨日の違いは何ですか? –

答えて

1

あなたの質問に編集内容を読んだので、ここに私の次の試みがあります!

これの背後にある考え方は、すべてを格納するために1つのテーブルを使用しているということです。このテーブルは事実すべての変更ログです。次に、テーブルを直接操作するのではなく、ビューを使用して各アカウントの最新情報を提供します。また、各アカウントの「閉じる」状態を1日ごとに表示するビューも用意されています。

完全に変更履歴ではなく、1日に1行しか持たないようにこのデザインを簡単に変更できます。 (それが効果的にテーブルと同じだとして、その場合には、あなたは、2番目のビューを必要としません。)

CREATE TABLE Accounts (
    ID     int IDENTITY(1,1), 
    BusinessDate  smalldatetime NOT NULL, 
    Account    int NOT NULL, 
    InitialAmount  money NULL, 
    LetterDate   smalldatetime NULL, 
    LetterType   varchar(50) NULL, 
    Status    varchar(50) NULL, 
    Reason    varchar(50) NULL, 
    FollowUpDate  smalldatetime NULL, 
    LastModifiedBy  varchar(50) NULL, 
    LastModifiedDate datetime NULL 
) 

insert into Accounts 
values ({d '2011-08-01'}, 1234567890, -10, NULL, NULL, 'Reviewed', 'Check issue', NULL, 'User', NULL), 
    ({d '2011-08-02'}, 1234567890, -50, NULL, NULL, 'Reviewed', 'Check issue', NULL, 'DataLoad', NULL), 
    ({d '2011-08-02'}, 1234567890, -50, NULL, NULL, 'Resolved', 'None', NULL, 'User', NULL), 
    ({d '2011-08-02'}, 1234567891, -20, NULL, NULL, 'Reviewed', 'Check issue', NULL, 'DataLoad', NULL) 
GO 

create view AccountsLatest 
as 
select a.* 
from Accounts a inner join 
    ( 
     select a.Account, MAX(a.ID) as ID 
     from Accounts a 
     group by a.Account 
    ) mx on a.ID = mx.ID 
GO 

create view AccountLatestByDate 
as 
select a.* 
from Accounts a inner join 
    ( 
     select a.Account, a.BusinessDate, MAX(a.ID) as ID 
     from Accounts a 
     group by a.Account, a.BusinessDate 
    ) mx on a.ID = mx.ID 
GO 
にロードされるファイルについては

、とに「前方コピー」いくつかのデータを必要とし、十分それはそうのようなものを扱うことができます。

--For simplicity's sake, I'm creating a load table that you simply clear and append your file contents to every night 
create table MyFile (
    BusinessDate  smalldatetime NOT NULL, 
    Account    int NOT NULL, 
    InitialAmount  money NULL, 
) 

insert into Accounts 
select f.BusinessDate, f.Account, f.InitialAmount, a.LetterDate, a.LetterType, a.Status, a.Reason, a.FollowUpDate, a.LastModifiedBy, a.LastModifiedDate 
from MyFile f inner join 
    AccountsLatest a on f.Account = a.Account 

私はこれがあなたのために多少OKの出発点として機能します願っています - それは明らかにあなたの正確なニーズに合わせて精製を必要とします。

私は、現在の解決策がちょっとしたことだと思うので、あなたはこれの背後にあるプロセスに疑問を持っていると思います。それはうまくいくかもしれないが、それは理想から遠くに聞こえる。私はあなたのビジネスについて何も知らないのですが、その背後にあるビジネスプロセスもちょっとしたことかもしれません。このプラットフォームの移行の機会を少なくとも取っておくと価値があるかもしれません。

(後世のために)ORIGINAL ANSWER

あなたが日から日まで静止したままのアカウント、および日付固有であり、他のデータについてのデータを持っていれば、その後、私はそれらを分離することになりますデータセットを独自のテーブルに格納します。これにより、ある日から次の日にデータをコピーする必要がなくなります。今、毎晩AccountDetailsの内容はAccountDetailsHistoryに移動し、ファイルの内容がAccountDetailsにロード

CREATE TABLE dbo.Accounts (
    Account int NOT NULL PRIMARY KEY, 
    InitialAmount money NULL, 
    Status varchar(50) NULL, 
    Reason varchar(50) NULL, 
    LastModifiedBy varchar(50) NULL, 
    LastModifiedDate datetime NULL 
) 

CREATE TABLE dbo.AccountDetails (
    BusinessDate smalldatetime NOT NULL, 
    Account int NOT NULL, 
    Guid uniqueidentifier NOT NULL, 
    LetterDate smalldatetime NULL, 
    LetterType varchar(50) NULL, 
    FollowUpDate smalldatetime NULL, 
    LastModifiedBy varchar(50) NULL, 
    LastModifiedDate datetime NULL 
) 

--This table will contain all the historic data that used to be in AccountDetails 
CREATE TABLE dbo.AccountDetailsHistory (
    BusinessDate smalldatetime NOT NULL, 
    Account int NOT NULL, 
    Guid uniqueidentifier NOT NULL, 
    LetterDate smalldatetime NULL, 
    LetterType varchar(50) NULL, 
    FollowUpDate smalldatetime NULL, 
    LastModifiedBy varchar(50) NULL, 
    LastModifiedDate datetime NULL 
) 

:だからあなたのテーブルは、この(どの列が静的なままにと、私は推測している)のようになります。 。 「コピー転送」しなければならないデータは、アカウントに保存されており、変更されていません。

AccountDetailsテーブルを1つしか持たず、必要に応じて分割することもできます。ここでは、パーティション化の仕組みとそれを使用するかどうかについてはまともな記事があります:http://msdn.microsoft.com/en-us/library/ms345146%28v=sql.90%29.aspx、これは設定が簡単であることを示しています:http://blogs.msdn.com/b/manisblog/archive/2009/01/18/easy-table-partitions-with-sql-server-2008.aspx

希望すると便利です。

+0

フィードバックに感謝しますが、アカウントテーブルのステータス、理由などは、その日のデータを処理しているユーザーに基づいて変更されるという問題があります。したがって、値はその日の開始点として前方にコピーされ、ユーザーはその日の更新を行います。しかし、昨日の勘定に関連付けられているので、昨日から値を保持する必要があります。混乱、ええ私も? – Taryn

+0

あなたの更新された回答で、私は私の元の設定を変更することができました。私は今行くのが良いと思う。助けてくれてありがとう。 – Taryn

+0

私は助けてくれることを嬉しく思います - プロジェクトには幸運があります! –

0

データストレージ要件とワークフロー要件が混在しているようです。 SQL Serverはデータの保存に最適ですが、ワークフロー要素の管理にはいくつかのオプションがあります。ストアドプロシージャを使用してワークフローまたはSQL Server Integration Services(SSIS)を管理することができます。

概要の問題は、最新のスナップショット(データが変更された日ごとに1つ)を必要とするように見えるため、最新のスナップショットを毎日表示すれば十分です。また、実際にすべての日中取引を記録して追跡できる必要がある場合は、テーブルを2つに分割することもできます(トランザクションと毎日のスナップショット)が、おそらく必要ないと思います。あなたは既に存在しているものに応じて、適宜挿入してコピーしてデータを作成する手順を使用し、SQL Server内のすべてのものを維持するための手順ソリューション

をストアド

次のスクリプト1つのサンプルデータアカウントでAccountDetailsというテーブルを設定します。

CREATE TABLE [dbo].AccountDetails(
    [BusinessDate] [smalldatetime] NOT NULL, 
    [Account] [int] NOT NULL, 
    [Guid] [uniqueidentifier] NOT NULL, 
    [InitialAmount] [money] NULL, 
    [LetterDate] [smalldatetime] NULL, 
    [LetterType] [varchar](50) NULL, 
    [Status] [varchar](50) NULL, 
    [Reason] [varchar](50) NULL, 
    [FollowUpDate] [smalldatetime] NULL, 
    [LastModifiedBy] [varchar](50) NULL, 
    [LastModifiedDate] [datetime] NULL 
) ON [PRIMARY] 

INSERT INTO AccountDetails 
VALUES ('2011-01-01', 123, NEWID(), 20, '2011-01-01', 'initial', 'reviewed', 'check issue', '2011-01-02', 'dwb',GETDATE()) 

ストアドプロシージャAccountDetailsControllerあなたはどちらかにできます

  • 更新今日のエントリを持っている既存のアカウント。 nullとして渡されたフィールドは、前のレコードの値を引き継ぎます。
  • 以前に入力したアカウントの詳細に基づいて新しいレコードを挿入します。これは、すでに設定済みのアカウントを持っているが、特定の詳細を更新したいというシナリオに対応しています。 nullとして渡されたフィールドは、前のレコードの値をとる。
  • 以前に入力したアカウントの詳細は新しいレコードを挿入する。新規アカウント。すべてのフィールドが初めて挿入されます。

CREATE PROCEDURE AccountDetailsController 
    @BusinessDate smalldatetime , 
    @Account [int] , 
    @Guid [uniqueidentifier] , 
    @InitialAmount [money] , 
    @LetterDate smalldatetime, 
    @LetterType varchar(50) , 
    @Status varchar(50) , 
    @Reason varchar(50) , 
    @FollowUpDate smalldatetime, 
    @LastModifiedBy varchar(50) 
AS 
BEGIN 

/* 
-- test bed 
-- remove when finished testing 
    DECLARE 
    @BusinessDate smalldatetime = '2011-01-01', 
    @Account [int] =123, 
    @Guid [uniqueidentifier] =null , 
    @InitialAmount [money] =30 , 
    @LetterDate smalldatetime = '2011-01-01', 
    @LetterType varchar(50) ='initial', 
    @Status varchar(50) = 'reviewed', 
    @Reason varchar(50) = 'check issue', 
    @FollowUpDate smalldatetime = null, 
    @LastModifiedBy varchar(50) = 'dwb' 
*/ 

    IF EXISTS (SELECT * FROM AccountDetails WHERE DateDiff(DAY,BusinessDate, @BusinessDate) = 0 AND @Account = [account]) 
    BEGIN 
     --RECORD ALREADY EXISTS FOR TODAY, UPDATE 
     UPDATE AccountDetails 
     SET  BusinessDate = ISNULL(@BusinessDate, BusinessDate), 
       [guid] = ISNULL(@Guid, [guid]), 
       InitialAmount = ISNULL(@InitialAmount, InitialAmount), 
       LetterDate = ISNULL(@LetterDate, LetterDate), 
       LetterType = ISNULL(@LetterType, LetterType) , 
       [Status] = ISNULL(@Status ,[Status]) , 
       Reason = ISNULL(@Reason, reason) , 
       FollowUpDate = ISNULL(@FollowUpDate, FollowUpDate), 
       LastModifiedBy = ISNULL(@LastModifiedBy, LastModifiedBy) , 
       LastModifiedDate = GETDATE() 
     FROM AccountDetails ad 
     WHERE DateDiff(DAY,BusinessDate, @BusinessDate) = 0 
     AND  @Account = [account] 
    END 
    ELSE IF EXISTS (SELECT * FROM AccountDetails WHERE @Account = [account]) 
    BEGIN 
     --RECORD ALREADY EXISTS, BUT FOR ANOTHER DAY. USE THIS AS THE BASIS OF TODAYS RECORD 
     INSERT INTO AccountDetails 
     SELECT @BusinessDate, 
       @Account, 
       ISNULL (@Guid, ad.guid), 
       ISNULL(@InitialAmount, InitialAmount), 
       ISNULL(@LetterDate, LetterDate), 
       ISNULL(@LetterType, LetterType) , 
       ISNULL(@Status ,[Status]) , 
       ISNULL(@Reason, reason) , 
       ISNULL(@FollowUpDate, FollowUpDate), 
       ISNULL(@LastModifiedBy, LastModifiedBy) , 
       GETDATE() 
     FROM AccountDetails ad 
     WHERE Account = @Account 
     AND  BusinessDate = 
     ( 
      SELECT MAX(BusinessDate) 
      FROM AccountDetails 
      WHERE @Account = [account] 
     ) 
    END 
    ELSE 
    BEGIN 
     --NO PREVIOUS RECORD EXISTS 
     INSERT INTO AccountDetails 
     VALUES (@BusinessDate, 
       @Account, 
       @Guid, 
       @InitialAmount, 
       @LetterDate, 
       @LetterType, 
       @Status, 
       @reason , 
       @FollowUpDate, 
       @LastModifiedBy , 
       GETDATE()) 

    END 

END 

以下は、すべてのシナリオに対応する必要があります。

--update a record that exists for today 
exec AccountDetailsController '2011-01-01', 123, null, 30, '2011-01-01', 'initial', 'reviewed', 'check issue', null, 'dwb' 

--create a new record based on the last date entered for account 
exec AccountDetailsController '2011-01-02', 123, null, 50, null, 'considered', null, null, null, 'dwb' 

--create an entirely new record, no previous account exists 
exec AccountDetailsController '2011-01-02', 456, 'C9CA5430-6D0E-47A3-BC89-D95C53B888E4' , 10, '2011-01-03', 'opened', 'new account', 'unknown','2011-01-03','dwb' 

この結果、次のようになります。 Results of test data applied to AccountDetailsController

SSISソリューション

ビジネスロジックとワークフローはあなたが提供する例よりも複雑である場合は、SSISは、データを管理し、制御することが検討する必要があります。これにより、SQLからソリューションが取り出され、最初はセットアップオーバーヘッドが発生しますが、データに何が起きているのかがより明確になり、時間の経過とともに、特にインポートされたファイルの管理が容易になります。

関連する問題