今天关于我的第二个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。
答案 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连接的左侧。
请让我知道这是怎么回事,如果它不能正常工作,我会调整它。我相信我们可以获得一个非常好的查询。