我无法让查询工作。我想要做的是按用户ID计算一个计数器,但条件是。
目前我的查询提供以下输出。
User ID EndDate Date Index
123 5/1/12 1/1/12 -1
123 5/1/12 1/25/12 1
123 5/1/12 2/13/12 -1
456 4/1/12 1/18/12 -1
456 4/1/12 2/15/12 -1
456 4/1/12 2/18/12 1
我想用这个列表做的是按用户ID加上索引但是有一个catch。索引必须按日期顺序求和,索引的最小值为-1,max为1,因此值只能为-1,0,1。因此,对于用户123,进程将为-1,然后您添加1然后添加-1以获得-1的最终总和。但是对于用户456,你从-1开始,然后你再次得到-1但是总和必须保持-1然后你有1,所以最后的总和是0.以下是我一直试图做的但是我无法想象出来。我真的很感激一些帮助。
DECLARE @Period char(6)
DECLARE @StatusCount int
SET @Period = '201201'
SET @StatusCount = 0
SELECT Q1.UserID, Q1.End_Date,
Sum(Case
When Index = -1 Then Case When @IndexCount >=0 Then @IndexCount - 1 Else @IndexCount + 0 End
When Index = 1 Then Case When @IndexCount <=0 Then @IndexCount + 1 Else @IndexCount + 0 End
END) as FinalIndex
FROM
(
(SELECT UserID, End_Date, Enter_Dt, 1 as Index
FROM UserTable
WHERE (Code in ('A', 'B') and PRD = @Period)
GROUP BY UserID, End_Date, Enter_Dt)
UNION
(SELECT UserID, End_Date, Enter_Dt, -1 as Index
FROM UserTable
WHERE (Code in ('C', 'D') and PRD = @Period)
GROUP BY UserID, End_Date, Enter_Dt)
) as Q1
GROUP BY Q1.UserID, Q1.End_Date
ORDER BY Q1.UserID ASC, Q1.End_Date ASC
我认为我的主要问题是我无法弄清楚如何正确积累指数。我无法让IndexCount记住之前的值,然后从0开始再次使用下一个用户ID
我使用此查询得到的结果是
User ID EndDate Index
123 5/01/12 -1
456 4/01/12 -1
这只是汇总指数
答案 0 :(得分:0)
听起来你需要定义循环序列:
http://www.postgresql.org/docs/8.1/static/sql-createsequence.html
这将创建您在问题中描述的效果,循环-1,0,1作为行迭代。您可以在选择中或在表中插入记录时实现此目的。
答案 1 :(得分:0)
我将在此处通过userID解决方案说明运行总计,为了清晰起见,省略了查询的其他详细信息。基本上,添加一个IndexRT列,用一个为每个新用户ID重置的运行总计填充它。
编辑:将运行总数限制为-1,0,1
create table #temp(userID int, [Index] int, IndexRT int)
insert into #temp (userID,[Index]) values (123,-1) , (123,1) , (123,-1) , (456,-1) , (456,-1) , (456,1)
declare @rt int; set @rt=0;
with a as (
select select TOP 100 percent *
,r=ROW_NUMBER()over(partition by userID order by userID)
from #temp order by userID,ROW_NUMBER()over(partition by userID order by userID)
)
update a set @rt = [IndexRT] = case when case when r=1 then [Index] else @rt + [Index] end between -1 and 1
then case when r=1 then [Index] else @rt + [Index] end
else @rt
end
select * from #temp;
go
drop table #temp;
结果:
userID Index IndexRT
----------- ----------- -----------
123 -1 -1
123 1 0
123 -1 -1
456 -1 -1
456 -1 -1
456 1 0
答案 2 :(得分:0)
这使用游标,似乎在SQL 2005中工作(我建议彻底检查你的结果,以防我错过了一些明显的东西)。
作为免责声明,大多数数据库专家会告诉您游标是可怕的,低效的,不应该使用。是的 - 你应该尽可能使用直接的SELECT语句。但是:(1)我不知道这种类型的累积有一个简单的SELECT语句,(2)对于任何必须维护代码的人来说,这将是一个更易读的解决方案。如果您的数据集不是非常大(并且您不希望它增长太多),那么游标应该没问题。
请注意,我已将“Table3”替换为整个FROM语句;我导入了您的示例表来创建此示例。这里要注意的关键要素是我首先按用户ID排序,然后按DECLARE csrOrdered CURSOR
语句中的日期排序。因此,您只需要在游标定义中替换自己的已排序SQL语句。
CREATE TABLE #sumResult (
[User ID] int,
[Sum Result] int
)
DECLARE csrOrdered CURSOR FOR
SELECT [User Id], [Index] FROM Table3 -- <- your table name goes here!
ORDER BY [User ID], Date, EndDate
DECLARE @uid int
DECLARE @index int
DECLARE @lastUid int
DECLARE @curSum int
SET @uid=0
SET @index=0
SET @lastUid=0
SET @curSum=0
OPEN csrOrdered
FETCH NEXT FROM csrOrdered
INTO @uid, @index
WHILE @@FETCH_STATUS=0
BEGIN
--Are we working on a new User ID? Then reset the sum and insert the last group into the table.
IF @uid<>@lastUid BEGIN
--Don't do an insert if we just got into the loop
IF @lastUid <> 0 BEGIN
INSERT INTO #sumResult ([User ID], [Sum Result]) VALUES (@lastUid, @curSum)
END
SET @curSum=0
SET @lastUid=@uid
END
SET @curSum = @curSum + @index
IF @curSum < -1 SET @curSum=-1
IF @curSum > 1 SET @curSum=1
FETCH NEXT FROM csrOrdered
INTO @uid, @index
END
IF @lastUid <> 0 BEGIN
INSERT INTO #sumResult ([User ID], [Sum Result]) VALUES (@lastUid, @curSum)
END
CLOSE csrOrdered
DEALLOCATE csrOrdered
SELECT * FROM #sumResult
DROP TABLE #sumResult