当count达到一个值时,获取第一个字段

时间:2011-04-14 08:57:23

标签: sql sql-server tsql

我需要在订单数量达到特定值的第一个日期对客户进行细分。

例如,我们有一个订单表

ID, ClientID, Date

1,  1, 1/1/2011
2,  1  2/1/2011
3,  1  3/1/2011
4,  1  4/1/2011

我想获得至少有3个订单的所有客户,并在达到3个订单时获得日期字段。 在我的例子中,查询将显示:

ClientID: 1, Date: 3/1/2011

(因为2011年3月1日,客户达到3个订单)

我该怎么做?

由于

更新

我正在寻找你的解决方案(非常感谢!)但是我也需要用SUM做同样的事情(假设上面的表有一个名为amount的字段,我想分割客户端并得到客户订单达到100美元的第一个日期) 我虽然解决方案将帮助我理解逻辑并轻松将计数转换为求和并进行新的查询但我在这里有点丢失..任何想法?

4 个答案:

答案 0 :(得分:1)

我会按照以下方式做点什么:

DECLARE @ClientId int, @RowNumber int
SELECT @ClientId = 1, @RowNumber = 3

SELECT ClientId, [Date]
FROM 
(
    SELECT TOP (@RowNumber) ClientId, [Date], ROW_NUMBER() OVER(ORDER BY ID) AS RowNumber
    FROM Test
    WHERE ClientId = @ClientId
) D
WHERE RowNumber = @RowNumber

您可以将客户端ID和行数作为参数处理,以用于您最终使用的任何过程。

答案 1 :(得分:0)

这样的事情:

SELECT clientid, date
FROM (
     SELECT id, 
            clientid, 
            row_number() over (partition by clientid order by date) as running_count,
            date
     FROM orders
) t
WHERE running_count = 3

修改
由于SQL Server中对窗口函数的不完全支持,我的解决方案无法扩展到涵盖sum()要求。

但为了完整起见,我尽可能地举了一个例子:

SELECT clientid, date
FROM (
     SELECT id, 
            clientid, 
            row_number() over (partition by clientid order by date) as running_count,
            sum(amount) over (partition by clientid order by date) as running_sum,
            date
     FROM orders
) t
WHERE running_sum = 100
   OR running_count = 3

但是再次:这将 在SQL Server中工作

答案 2 :(得分:0)

这将选择所有具有3个订单且具有第3个订单日期的客户。

--DECLARE @clientID INT
--SET @clientID = 1
DECLARE @count INT
SET @count = 3      -- Set the count to this variable.

SELECT  ClientID, [Date]
FROM    [yourtable] a
WHERE   COALESCE(    (SELECT COUNT(*) 
                      FROM [yourtable] b 
                      WHERE b.[Date] < a.[Date] and b.ClientID = a.ClientID ),0) = @count - 1
ORDER BY ClientID

选择具有第三个订单日期的单个客户,其中可以使用附加条件进行修改。

AND a.ClientID = @clientID
基于问题更新的

更新 - 这个查询几乎没有来自count woud的修改,可以为您提供运行总和选择。此处列出了running sum的更多技术。

DECLARE @sum INT
SET @count = 100      -- Set the amount to this variable.

SELECT  ClientID, [Date]
FROM    [yourtable] a
WHERE   ( a.Amount + COALESCE(    (SELECT SUM(b.Amount) 
                      FROM [yourtable] b 
                      WHERE b.[Date] < a.[Date] and b.ClientID = a.ClientID ),0) ) = @sum
ORDER BY ClientID

答案 3 :(得分:0)

测试表和测试数据

declare @T table (ID int, ClientID int, [Date] datetime, Amount money)

insert into @T values
(1,  1,  '1/1/2011', 10),
(2,  1,  '2/1/2011', 20),
(3,  1,  '3/1/2011', 30),
(4,  1,  '4/1/2011', 40),
(5,  2,  '1/1/2011', 10),
(6,  2,  '2/1/2011', 20),
(7,  2,  '3/1/2011', 30)

获得第三排并不是那么难。这与提供的a_horse_with_no_name解决方案相同。

declare @Row int = 3

;with cte as 
(
  select *,
    row_number() over(partition by ClientID order by [Date]) as rn
  from @T
)  
select *
from cte
where rn = @Row

要在运行总和超过某个值时获取该行有点困难。这是一个循环版本,使用临时表来更新运行总和。

declare @sum money = 30

select *, cast(0 as money) as Running
into #T
from @T

declare @rn int = 1

;with cte as
(
  select
    Running,
    Amount,
    row_number() over(partition by ClientID order by [Date]) as rn
  from #T
)  
update cte set
  Running = Amount
where
  rn = @rn

while @@rowcount >= 1
begin
  set @rn = @rn + 1

  ;with cte as
  (
    select
      Running,
      Amount,
      row_number() over(partition by ClientID order by [Date]) as rn
    from #T
  )  
  update cte set
    Running = Running + Amount
  where rn = @rn
end

;with cte as
(
  select *,
    row_number() over(partition by ClientID order by [Date]) as rn
  from #T
  where Running >= @sum
)
select *
from cte
where rn = 1

drop table #T