如何找出给定项目的字段值是不是仅增加?

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 开始提供的。

这就是想法。首先通过statedate 枚举每个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
)

【讨论】:

以上是关于如何找出给定项目的字段值是不是仅增加?的主要内容,如果未能解决你的问题,请参考以下文章

节点快递:如何找出给定etag的状态是不是为304

如何在 Quickblox 中找出用户是不是在线?

SAP采购申请行项目中如何增加字段?十分感谢!

jira 创建项目时候如何增加自定义字段?

给定一个特征向量,如何找出我的数据点是不是线性可分

检查输入到文本字段的值是不是是给定范围内的整数