Sql server Sql MAX DateTime和if子句?
今天我的第二个Sql问题是关于SO的-我需要复习我的Sql技能 我有以下三张桌子Sql server Sql MAX DateTime和if子句?,sql-server,sql,Sql Server,Sql,今天我的第二个Sql问题是关于SO的-我需要复习我的Sql技能 我有以下三张桌子 日记、条目和条目类型 SELECT FROM Diary D CROSS APPLY ( SELECT TOP 1 E.EntryID FROM Entry E WHERE D.DiaryID = E.DiaryID AND E.CreatedDatetime > @LastDateTime
日记、条目和条目类型
SELECT
FROM
Diary D
CROSS APPLY (
SELECT TOP 1 E.EntryID
FROM
Entry E
WHERE
D.DiaryID = E.DiaryID
AND E.CreatedDatetime > @LastDateTime
AND EXISTS (
SELECT 1 FROM EntryType ET
WHERE E.EntryTypeID = ET.EntryTypeID
AND ET.SomeOtherValue <> 0 -- or = @SomeValue ?
)
ORDER BY CreatedDatetime DESC
)
日记可以有许多条目,每个条目都有一个特定的条目类型
条目具有已创建的日期时间
EntryType有一个Id和SomeOtherValue int
编辑
对不起,伙计们。感谢您的回复,但我解释得不够好;要求有点变化
我想要任何日记的Id,其中其最新条目大于@lastDateTime和EntryType.someOthervalue!=0具有EntryType。someOthervalue==@someValue
或者换一种方式……对于所有创建日期时间>@lastDateTime的条目行,忽略等于0的SomeOther值,如果剩余的前1有someOtherValue=@someValue,则返回日记的Id
这有意义吗???我不知道我应该把我的最大值放在哪里,如果有的话
谢谢
Etfirfax.像这样的东西怎么样:
select d.diary_id
from diary d
join entry e on(d.diary_id = e.diary_id)
join entry_type et on(e.entry_type_id = et.entry_type_id)
where et.someOthervalue = @someValue
group by d.diary_id
having max(e.created) > @lastDateTime;
如果您使用的是SQLServer2005,另一种方法是+
With EntryDates As
(
Select E.DiaryId
, Max(E.Created) Over ( Partition By E.DiaryId ) As LastCreateDate
From Entry As E
Join EntryType As ET
On ET.Id = E.EntryTypeId
Where ET.SomeOtherValue = @SomeValue
)
Select DiaryId
From EntryDates
Where LastCreateDate > @lastDateTime
Group By DiaryId
如果您想要最后一个条目,然后使用最后一个条目,测试最后一个条目的entrytype是否为@somevalue,那么这应该是正确的查询
select diaryid
from (
select rn=row_number() over (partition by e.diaryid order by e.created desc),
d.diaryid, et.someothervalue
from entry e
inner join entrytype et on e.entrytype = et.id
where e.created > @lastDateTime
) X
where rn=1
and SomeOtherValue = @someValue -- of the last record
但是,如果您的意思是@somevalue的条目类型中有一个是最新的>@lastDateTime,那么它就是
select e.diaryid
from entry e
inner join entrytype et on e.entrytype = et.id
where et.SomeOtherValue = @someValue
group by e.diaryid
having max(e.created) > @lastDateTime
注意:对于具有适当引用的数据库,可以从条目中导出日志id,而无需返回日志。链接回日记的唯一原因是,如果您需要完整的日记记录,或者如果没有外键,您需要验证日记id是否存在
对于第二种类型,还有另一种编写方法,它仍然符合ANSI标准,并且可能更快。这是通过推断创建的最大e.大于@lastdatetime的任何记录来实现的
编辑:正如Andrey在本语句前面的第二个查询中指出的,HAVING子句可以基于相同的事实移动到WHERE子句,但我将查询保留为该形式,以匹配需求的表达,而不使用推导的简化
select e.diaryid
from entry e
where exists (
select *
from entrytype et
where e.entrytype = et.id
and et.SomeOtherValue = @someValue)
and e.created > @lastDateTime
GROUP BY e.diaryid
此存在性测试可以在找到一个与somevalue匹配并已创建的条目后立即停止检查条目的entrytypes,而不是在HAVING子句中将其向下筛选之前完全处理联接和聚合max。日记、条目和条目类型
SELECT
FROM
Diary D
CROSS APPLY (
SELECT TOP 1 E.EntryID
FROM
Entry E
WHERE
D.DiaryID = E.DiaryID
AND E.CreatedDatetime > @LastDateTime
AND EXISTS (
SELECT 1 FROM EntryType ET
WHERE E.EntryTypeID = ET.EntryTypeID
AND ET.SomeOtherValue <> 0 -- or = @SomeValue ?
)
ORDER BY CreatedDatetime DESC
)
CreatedDatetime条目中的索引可能会有所帮助,但表的聚集索引应该有DiaryID,或者索引应该将其作为索引列之一包含
我假设EntryTypeID表与其他表相比很小,所以它很可能是一个表扫描,所以索引不会有多大帮助。如果您的执行计划在EntryType表上读取了大量数据,请告诉我,我们将尝试修复它。我希望引擎足够聪明,能够意识到这个表很小,只需要点击一次,然后把它放在某个地方的循环连接的左侧
请让我知道这是怎么回事,如果它不工作的权利,我会调整它。我相信我们可以得到一个性能非常好的查询。您的第三种方法可能应该使用DISTINCT或grouping:我认为没有理由选择可能存在的重复的diaryid值。在你的第二个例子中,我认为将having条件转换为where是有效的,而且在性能方面可能更好,也就是where将如下所示:where et.SomeOtherValue=@someValue和e.created>@lastDateTime。无论如何,在这样的查询中不使用日记是一个很好的观点,这样做的原因也值得一提+1@Andriy-感谢您的评论,我已将group by添加到第三次查询第二次口译的方法中。第二个和第三个与第一个意思不同。第二篇是特意写的,目的是准确地表达这个问题——找到所有X类型的条目,然后将该结果创建的最大值与@date进行比较,所以我将不谈这个问题。尽管我最初的帖子有一点变化,但这个回复包含了大量信息,帮助我最终实现了我所需要的。非常感谢。仅供参考,像Max OVER这样的窗口聚合可能会降低性能。我看到了。添加一个额外的CTE和一个真正的Max和一个组,一次完全拯救了我的查询。