好的,这是一个头部清障车,我会尽量保持简短。
我有两个表,Security和SecurityAudit 只有在进行更改时,Audit表才会保留对Security表的任何更改的副本。 SecurityId是Foriegn键。因此,最近的记录总是在安全表中,如果有更改,则将其写入Audit表,并将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,联盟和Rank来做到这一点,但是我已经撞墙了。到目前为止它看起来像这样......
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且没有子记录的所有证券...即审计表中的子计数为0且审计记录小于我正在寻找的日期并采取最重要的一个。
所以我到目前为止。我是在正确的轨道上,烹饪它,还是只是疯狂计划。任何帮助将不胜感激。
问候M
答案 0 :(得分: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大于我们正在查看的日期。
答案 1 :(得分:0)
好的,这就是我约会的日期...... Galador ......我会看看你的朋友,因为它看起来更好......我唯一关心的是这是多么高效...我不希望安全表在一年内超过30,000条记录,并且有大约300,000条审计
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