Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server Sql MAX DateTime和if子句?_Sql Server_Sql - Fatal编程技术网

Sql server Sql MAX DateTime和if子句?

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

今天我的第二个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
         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和一个组,一次完全拯救了我的查询。