【问题标题】:Group by not working with cursor通过不使用光标进行分组
【发布时间】:2011-12-13 11:20:50
【问题描述】:

考虑以下查询。 我为此查询创建了一个游标。 我的问题是 group by 在游标中无法正常工作。但是当我执行查询时,它给出了完美的 group by 结果。

当我使用 FETCH NEXT 和 WHILE 循环迭代游标时,它会为同一个 point_id 提供多个组。

你能帮我解决这个问题吗??? 提前谢谢..

select timestamp as 'TS',REPLACE(REPLACE(POINT_ID,'[','_'),']','_') AS POINT_ID,_VAL 
from TCF1_PULLCORD 
where timestamp between '11/01/2011 6:30:00 AM' and '12/01/2011 6:29:59 AM'
group by point_id,timestamp,_val


DECLARE MYCUR CURSOR 
FOR
    select timestamp as 'TS',REPLACE(REPLACE(POINT_ID,'[','_'),']','_') AS POINT_ID,_VAL 
    from TCF1_PULLCORD 
    where timestamp between '11/01/2011 6:30:00 AM' and '12/01/2011 6:29:59 AM'
    group by point_id,timestamp,_val

【问题讨论】:

  • “光标不能正常工作”是什么意思
  • 它给出 POINT_ID = 'DOOR_PROD_ST_1_' 的行,然后给出 POINT_ID = 'DOOR_PROD_ST_10_' 的行,然后给出 'DOOR_PROD_ST_11_' 的行,然后再给出 'DOOR_PROD_ST_1_' 的行......我的意思是分组被划分
  • @Dharmesh:请关闭您的 CAPS LOCK KEY - 这是在考虑 YELLING,这是 粗鲁
  • 哦,如果是这样,我真的很抱歉......马克
  • 您能告诉我们您是如何实现光标的吗?表结构?样本数据?

标签: sql sql-server sql-server-2008 tsql stored-procedures


【解决方案1】:

这是您的数据库表达“请不要在我身上使用光标”的方式。 :D

开个玩笑,但说真的,您会发现遍历表变量比使用游标具有更好的性能。

DECLARE @timestamps TABLE( 
    TS DATETIME,
    POINT_ID VARCHAR(100),
    _VAL VARCHAR(100)
    )
DECLARE @currTimeStamp DATETIME 

INSERT INTO @timestamps 
select timestamp as 'TS',REPLACE(REPLACE(POINT_ID,'[','_'),']','_') AS POINT_ID,_VAL 
from TCF1_PULLCORD 
where timestamp between '11/01/2011 6:30:00 AM' and '12/01/2011 6:29:59 AM'
group by point_id,timestamp,_val


WHILE (SELECT COUNT(TS) FROM @timestamps > 0)
BEGIN
    SELECT @currTimeStamp = MIN(TS) FROM @timestamps
    --Do work here
    ...

    --Delete the timestamp we just worked on
    DELETE FROM @timestamps WHERE TS = @currTimeStamp
END 

此外,除非您的 SELECT 正在执行我们在此处看不到的其他操作,否则 GROUP BY 应该是不必要的。如果您没有执行任何聚合函数(例如 SUM、MAX、MIN)并且您实际上只是想获得唯一的组合,那么 SELECT DISTINCT 是一种更有效的方法。

在这种情况下,您的选择将是:

select DISTINCT timestamp as 'TS',REPLACE(REPLACE(POINT_ID,'[','_'),']','_') AS POINT_ID,_VAL 
from TCF1_PULLCORD 
where timestamp between '11/01/2011 6:30:00 AM' and '12/01/2011 6:29:59 AM'

【讨论】:

  • 亲爱的乔纳森。你教会了我一个很好的方法,但它在处理 44021 行时花费了太多(超过 5 分钟)的时间。当我使用 select 语句显示@timestamps 表时,它给了我完美的结果[“INSERT INTO @timestamps”]。所以你的建议可能非常适合小结果(1000-2000)行
  • 当我使用 EXISTS(SELECT * FROM @timestamps) 时它变得更快。非常感谢乔纳森
  • 是的,EXISTS 在某些情况下可能更快。在许多情况下,向@timestamps 添加主键也可以提高性能。除非您手头有实际数据,否则对答案的优化总是一种猜测。
【解决方案2】:

不确定这是否会对您有所帮助,但至少更准确。

DECLARE MYCUR CURSOR 
FOR
    select  timestamp as 'TS'
            ,REPLACE(REPLACE(POINT_ID,'[','_'),']','_') AS POINT_ID
            ,_VAL 
    from    TCF1_PULLCORD 
    where   timestamp between '11/01/2011 6:30:00 AM' and '12/01/2011 6:29:59 AM'
    group by 
            REPLACE(REPLACE(POINT_ID,'[','_'),']','_')
            ,timestamp
            ,_val

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-10-09
    • 2020-06-28
    • 1970-01-01
    • 2021-06-02
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 2016-06-03
    相关资源
    最近更新 更多