如何找出给定项目的字段值是不是仅增加?
Posted
技术标签:
【中文标题】如何找出给定项目的字段值是不是仅增加?【英文标题】:How to find out if a field's values for a given item are only increasing?如何找出给定项目的字段值是否仅增加? 【发布时间】:2013-10-29 20:12:27 【问题描述】:对于这个问题,我使用 Access 作为 SQL Server 的前端,并通过 Excel VBA 调用 Access,但如果有一些 T-SQL 特定功能在这里会更有用,我可以使用直接 ADO 连接.
我有一个记录一组项目状态变化的表,例如:
+-------+-------+------------+
| 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 中编写一个可以对整个数据集执行相同类型分析的查询?
【问题讨论】:
对于您的问题,ADODB.Recordset 上的 VB 循环可能比 COMPLEX SQL 查询更有效。 【参考方案1】:Gordon Linoff 在他的出色回答中说:
您在使用仅限访问功能时遇到问题
真的吗?
对于给定的数据,我已将其放入名为 [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
然后我可以使用以下查询来识别 [docID] 的 [state] 下降
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
那么问题出在哪里?
【讨论】:
【参考方案2】:您在使用仅限访问功能时遇到问题。但是,如果您有 SQL Server 2012,则可以使用 lead()
/lag()
功能。还有另一种方法,就是使用row_number()
,它是从 SQL Server 2005 开始提供的。
这就是想法。首先通过state
和date
枚举每个docId
中的行。如果枚举相同,则序列是非递减的(本质上是递增的)。如果不同,则道路上有颠簸。代码如下:
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;
请注意,通过使用这两个字段,我使排序变得更加复杂。这可以处理连续两个日期具有相同状态的情况(可能不允许,但也可以使技术更稳定)。
【讨论】:
【参考方案3】:问题:
对于每个唯一的 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
)
【讨论】:
以上是关于如何找出给定项目的字段值是不是仅增加?的主要内容,如果未能解决你的问题,请参考以下文章