2011-10-25 15 views
0

okこれは頭部の破損者です。私はそれを簡潔に保つようにします。最新のレコードを取得するためのAuditテーブルのSQL Server CTE

私は2つのテーブルSecurityとSecurityAuditを持っています 監査テーブルは、変更があった場合にのみ、セキュリティテーブルの変更のコピーを保持します。 SecurityIdはForiegnキーです。だから、最近のレコードは、セキュリティテーブルに常にあり、変更、その監査テーブルに書き込まれ、ValidToDateは、レコードがここまで

[Security](
    [SecurityID] [bigint] IDENTITY(10000,1) NOT NULL, 
    [Security] [nvarchar](255) NOT NULL, 
    [ISIN] [nvarchar](20) NOT NULL, 
    [CountryOfIncID] [bigint] NOT NULL, 
    [SecurityTypeID] [bigint] NOT NULL, 
    [SubTypeID] [bigint] NOT NULL, 
    [ISQ] [bigint] NOT NULL, 
    [MemberStateID] [bigint] NULL, 
    [ManualOverride] [bit] NULL, 

に有効であった日付に設定されているがある場合、監査テーブルです

[SecurityAudit](
      [SecurityAuditID] [bigint] IDENTITY(10000,1) NOT NULL, 
      [SecurityID] [bigint] NOT NULL, 
      [Security] [nvarchar](255) NOT NULL, 
      [CountryOfIncID] [bigint] NOT NULL, 
      [SubTypeID] [bigint] NOT NULL, 
      [ISQ] [bigint] NOT NULL, 
      [MemberStateID] [bigint] NULL, 
      [ValidToDateID] [datetime] Not NULL 

私の今の問題は、特定の時点でプレーしているすべての証券を取得したいということです。これは、セキュリティテーブルから一度も変更されていないすべての証券を取得し、その時点の監査テーブルから関連するセキュリティを取得することを意味します。

私はCTEを使用してこれを行うだろうと思った、と連合とランクけど、壁にぶつかるまし。そのように見えるのはこれまでのところ...

With 
    cteAllSecurities (RowNum,SecurityID, Security, ISQ, CountryOfIncorporationID, ValidToDate) 
    AS 
    (
     SELECT RowNum=row_number() OVER (Partition By Security order by ValidToDate desc), 
      sa.SecurityID, sa.Security, sa.ISQ, sa.CountryOfIncorporationID, CONVERT(varchar(30), sa.ValidToDate,106) 
      FROM 
      SecurityAudit sa 
     UNION 
     SELECT 0 as RowNum, 
      s.SecurityID, s.Security, s.ISQ, s.CountryOfIncorporationID, CONVERT(varchar(30), GetUtcDate(),106) as ValidToDate 
      FROM 
      Security s 
    ) 
    SELECT RowNum, SecurityID, Security, ISQ, CountryOfIncorporationID, ValidToDate 
    FROM cteAllSecurities 
    order by securityid 
    Where row_number() = 1 

私は、監査を最後に持つSecuritesテーブルを結合して行番号を与えます。私は、行番号が0で子レコードがない証券をすべて取得することを望んでいました。つまり、監査テーブルに子カウントがあり、探している日付よりも小さい監査レコードがあります。一番上のもの

だから私はこれまでに得た。私は正しい道を歩いているか、それを料理しているか、ただ気違いを計画しています。どんな助けでも大歓迎です。

よろしくM

答えて

1

私はあなたがこのようなクエリを探している結果を得ることができる必要がありだと思う

AllSecurity (Security, ISQ, CountryOfIncorporationID, ValidToDate) 
AS (
    SELECT Security, ISQ, CountryOfIncID, CONVERT(DATETIME, '9999-12-31 23:59:59.997') 
    FROM Security 
     UNION 
    SELECT Security, ISQ, CountryOfIncID, ValidToDate 
    FROM SecurityAudit 
) 
SELECT TOP 1 Security, ISQ, CountryOfIncorporationID, ValidToDate 
FROM AllSecurity A 
WHERE ValidToDate = (
    SELECT MIN(ValidToDate) 
    FROM AllSecurity B 
    WHERE B.Security = A.Security 
     AND ValidToDate > @SearchDate 
) 

あなたは明らかに@SearchDateを交換したいと思いますあなたが探している価値

このクエリは、現在のセキュリティテーブルを結合し、ValidToDateをSQL Serverが受け入れる最大DATETIME値に設定し、それを監査テーブルと結合します。次に、サブクエリを使用して、私たちが見ている日付よりも大きい「最も近い」(最小の)ValidToDateを取得します。ここ

+0

でより多くのことができます。 Valid TOPDate> @SearchDate ORDER BY ValidToDateを選択する方が良いでしょう。また、選択リストで、ValidToDate = '99999-12-31 23:59:59.997'(CASEまたはISNULL(NULLIF ...)を使用する場合は、ValidToDateではなくGETDATE()を返すことをお勧めします) – GilM

+0

thanks galador ..私はあなたが正しいラインにいると思うが、あなたのものはちょっとばっちりしているので見てみよう。 – Doiremik

0

OKが私の唯一の他の懸念は、これがどのようにパフォーマンス..ですそれが良く見えるように私が今までに持っているもの... Galadorが...私はまた、あなたの友人を見て取得しますが...私は期待してはいけませんセキュリティテーブルは、同じValidToDateで2つの行を持つことが可能なら、同じSecurityIdため、SecurityAuditに、このソリューションは、それらの両方を返すことができます年30,000レコードのことをして30万人の監査

With 
    cteAllSecurities (RowNum,SecurityID, Security, ISQ, CountryOfIncorporationID, ValidToDate) 
    AS 
    ( -- Get all the securites and union the with the History records that we are interested in 
     SELECT RowNum=row_number() OVER (Partition By Security order by ValidToDate desc), 
      sa.SecurityID, sa.Security, sa.ISQ, sa.CountryOfIncID, CONVERT(varchar(30), sa.ValidToDate,106) 
      FROM 
      SecurityAudit sa 
      WHERE 
      ValidToDate >= Cast('08-22-2011' as datetime) -- filter out the records that we dont need 
     UNION 
     SELECT 0 as RowNum, -- make this Row num 0 so we can group on them 
      s.SecurityID, s.Security, s.ISQ, s.CountryOfIncID, CONVERT(varchar(30), GetUtcDate(),106) as ValidToDate 
      FROM 
      Security s 
    ), 
    cteMaxSecurties (SecurityID, MaxValidToDate) 
    AS 
    (
     -- now get all the securities and find out their max date... 
     select SecurityID, Max(ValidToDate) from 
      cteAllSecurities 
      Group by SecurityID 

    ) -- now join the max date and security 
    SELECT RowNum, cteAllSecurities.SecurityID, Security, ISQ, CountryOfIncID, ValidToDate 
    FROM cteAllSecurities Left Join cteMaxSecurties 
      on cteAllSecurities.SecurityID = cteMaxSecurties.SecurityID and cteAllSecurities.ValidToDate = cteMaxSecurties.MaxValidToDate 
    order by Security 
関連する問題