Sql MAX DateTime和if子句?

时间:2011-01-22 16:08:32

标签: sql-server sql

今天关于我的第二个Sql问题 - 我需要提高我的Sql技能!!!!

我有以下三个表....

Diary,Entry和EntryType

日记可以有多个条目,每个条目都是特定的条目类型。

条目有一个创建的DateTime EntryType有一个Id和SomeOtherValue(int)

修改

抱歉Chaps。感谢您的回复,但我没有解释得那么好;要求有所改变.....

我想要任何日记的ID,其最新条目大于@lastDateTime AND EntryType.someOthervalue!= 0有一个EntryType.someOthervalue == @someValue

或者换句话说....对于所有那些创建日期时间>的Entry行@lastDateTime,忽略等于0的someOtherValues,如果剩下的前1个有someOtherValue = @someValue,则返回日记的Id !!!!

这有意义吗?我不确定我应该把我的MAX,WHERE和HAVING放在哪里(如果有的话)!

谢谢,

ETFairfax。

4 个答案:

答案 0 :(得分:2)

如果您想要最后一个条目,然后with the last entry,请测试最后一个条目的条目类型是否为@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

注意:对于具有适当引用的数据库,可以从条目without going back to diary派生diary_id。链接回日记的唯一原因是,如果您需要完整的日记记录,或者如果没有外键,则需要验证diary_id是否存在。

对于第二种类型,还有另一种写入方式仍然符合ANSI标准且可能更快。这可以通过推导出MAX e.created大于@lastdatetime,任何记录

编辑:正如Andriy指出第二个查询(直接在此语句之前),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

这个EXIST实时测试可以在找到一个匹配的somevalue时立即检查条目的入口类型,并在HAVING子句中将其过滤之前创建而不是完全处理连接和聚合(max)。

答案 1 :(得分:0)

这样的事情怎么样:

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;

答案 2 :(得分:0)

如果您使用的是SQL Server 2005 +

,则另一种方法
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    

答案 3 :(得分:0)

Diary,Entry和EntryType

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上的Entry中的索引会有所帮助,但是表的聚簇索引应该具有DiaryID,或者索引应该将其作为索引列之一包含。

我认为EntryTypeID表与其他表相比较小,所以它最有可能是一个表扫描,因此索引不会有太大帮助。如果您的执行计划在EntryType表上获得了大量读取,请告诉我们,我们将尝试修复它。我希望引擎足够聪明,可以意识到这个表很小而且只打了一次,然后将它放在某个LOOP连接的左侧。

请让我知道这是怎么回事,如果它不能正常工作,我会调整它。我相信我们可以获得一个非常好的查询。