对于这个问题,我使用Access作为SQL Server的前端,并通过Excel VBA调用Access,尽管我可以使用直接的ADO连接,如果有一些T-SQL特定的函数在这里会更有用
我有一个表记录了一组项目的状态变化,例如:
+-------+-------+------------+
| docID | state | date |
+-------+-------+------------+
| 103 | 5 | 10/15/2013 |
| 103 | 6 | 10/18/2013 |
| 102 | 3 | 10/22/2013 |
| 103 | 2 | 11/1/2013 |
| 102 | 7 | 11/8/2013 |
+-------+-------+------------+
对于每个唯一的docID
,我想弄清楚它的状态是否仅从第一个日期到最后一个日期增加,或者它是否会减少。在上述数据集中,103减少,102仅增加。我们可以假设条目将按日期顺序排列。
找到这个的一种方法是为每个docID
创建一个对象,并将这些对象添加到字典中,将每个状态更改加载到一个列表中,并检查状态是否已减少,如下所示:
function isDecreasing(cl as changeList) as boolean
for c=2 to cl.count
if cl.item(c).state < cl.item(c-1).state then
isDecreasing=true
exit function
end if
next
isDecreasing=false
end function
但这会减慢我的查询速度,因为我必须将所有表数据转换为对象。这也意味着我将不得不编写大量额外的代码来创建和管理用于计算和生成报告的对象。
有没有办法在SQL Server或Access中编写可以对整个数据集执行相同类型分析的查询?
答案 0 :(得分:2)
在他出色的回答中,戈登林诺夫说:
使用仅限访问功能时出现问题
真的?
对于给定的数据,我将其放在一个名为[StateChanges]的表中:
docID state date
----- ----- ----------
103 5 2013-10-15
103 6 2013-10-18
102 3 2013-10-22
103 2 2013-11-01
102 7 2013-11-08
我可以在名为[PreviousDates]
的Access中创建以下保存的查询SELECT t1.docID, t1.date, MAX(t2.date) AS PreviousDate
FROM
StateChanges t1
INNER JOIN
StateChanges t2
ON t2.docID = t1.docID
AND t2.date < t1.date
GROUP BY t1.docID, t1.date
返回
docID date PreviousDate
----- ---------- ------------
102 2013-11-08 2013-10-22
103 2013-10-18 2013-10-15
103 2013-11-01 2013-10-18
然后我可以使用以下查询来识别[state]发生故障的[docID]
SELECT curr.docID
FROM
(
PreviousDates pd
INNER JOIN
StateChanges curr
ON curr.date = pd.date
)
INNER JOIN
StateChanges prev
ON prev.date = pd.PreviousDate
WHERE curr.state < prev.state
返回
docID
-----
103
事实上,这两个查询都非常简单,我们可以将它们组合成一个查询,一次完成整个过程:
SELECT curr.docID
FROM
(
(
SELECT t1.docID, t1.date, MAX(t2.date) AS PreviousDate
FROM
StateChanges t1
INNER JOIN
StateChanges t2
ON t2.docID = t1.docID
AND t2.date < t1.date
GROUP BY t1.docID, t1.date
) PreviousDates
INNER JOIN
StateChanges curr
ON curr.date = PreviousDates.date
)
INNER JOIN
StateChanges prev
ON prev.date = PreviousDates.PreviousDate
WHERE curr.state < prev.state
那么问题出在哪里?
答案 1 :(得分:1)
使用仅限访问功能时遇到问题。但是,如果您有SQL Server 2012,则可以使用lead()
/ lag()
功能。还有另一种方法,就是使用row_number()
,这是自SQL Server 2005以来可用的。
这是个主意。首先按docId
和state
枚举每个date
内的行。如果枚举相同,则序列不减少(基本上增加)。如果不同,那么道路上就会出现颠簸。这是代码:
select docid,
(case when sum(case when rn_ds <> rn_sd then 1 else 0 end) = 0 then 'Increasing'
else 'Decreasing'
end) as SequenceType
from (select d.*,
row_number() over (partition by docId order by date, state) as rn_ds,
row_number() over (partition by docId order by state, date) as rn_sd
from d
) d
group by docid;
请注意,我使用这两个字段使得排序更加复杂。这处理了一行中两个日期具有相同状态的情况(可能不允许,但也可能使技术更稳定)。
答案 2 :(得分:0)
问题:
对于每个唯一的docID,我想弄清楚它的状态是否只是从第一个日期到最后一个日期增加,或者它是否会减少。
所以你想要知道的是,对于给定的记录a,exist
有一个记录b
,a
的日期早于b
的状态select docID
from T a
where
exists (
select 1 from T b where b.date > a.date and b.state < a.state
)
低了。
所以请问。
{{1}}