聚合具有等级或索引的行> = N.

时间:2016-03-30 08:24:09

标签: sql sql-server postgresql

我有一个加入我的客户和交易表的查询,我们将此加入的查询别名为Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim cTab As Integer Dim BaseSht As Worksheet Dim NewSht As Worksheet Set BaseSht = ActiveSheet cTab = ActiveCell.Row - 1 If Selection.Count = 1 Then If Not Intersect(Target, Range("A2:A201")) Is Nothing Then Dim WS1 As Worksheet On Error Resume Next Set WS1 = Worksheets(cTab & ".") If WS1 Is Nothing Then Application.ScreenUpdating = False ActiveCell = cTab & "." Sheets("Template").Visible = True Sheets("Template").Copy After:=Sheets(Worksheets.Count) ActiveSheet.Name = cTab & "." Set NewSht = ActiveSheet BaseSht.Select 'Copy row to new sheet BaseSht.Range(ActiveCell.Address & ":" & BaseSht.Cells(ActiveCell.Row, Columns.Count).End(xlToLeft).Address).Copy NewSht.Range("A" & cTab + 1) 'Sheets("Template").Visible = False Application.ScreenUpdating = True Else Sheets(cTab & ".").Select End If End If End If End Sub 。我想按订单时间戳(jq)创建每个客户的购买(交易)排名。所以我做到了,

order_ts

现在,我希望第5次购买是聚合的单行,而不是第5,第6,第7,依此类推。求和的行将保留第5行SELECT customer_id, order_id, order_ts, RANK() OVER (PARTITION BY customer_id ORDER BY order_ts ASC), amount FROM jq GROUP BY customer_id ORDER BY customer_id; order_id。我如何在MS SQL Server和Postgres中执行此操作?

3 个答案:

答案 0 :(得分:3)

如果我理解正确,您可以使用CASE EXPRESSION

来实现这一目标
SELECT customer_id,min(order_id),min(order_ts), CASE WHEN rnk < 5 then rnk else 5 end as rnk,sum(amount)
FROM(
    SELECT customer_id, 
           order_id, 
           order_ts, 
           RANK() OVER (PARTITION BY customer_id ORDER BY order_ts ASC) as rnk, 
           amount 
    FROM jq)
GROUP BY customer_id,
         CASE WHEN rnk < 5 then rnk else 5 end
ORDER BY customer_id

这将对每个rnk进行分组&gt; 5为5,为1组。我选择了min order_id,ts从第5个选择它。

答案 1 :(得分:3)

  

虽然这会产生正确的结果,但sagi的answer效率更高。

您可以在结果上使用SELECT并过滤RANK < 5。然后对UNION ALL

的汇总值执行RANK >= 5
WITH Cte AS(
    SELECT 
        customer_id, 
        order_id, 
        order_ts, 
        RANK() OVER (PARTITION BY customer_id ORDER BY order_ts ASC) AS rnk, 
        amount 
    FROM jq 
    GROUP BY customer_id 
)
SELECT
    customer_id,
    order_id,
    order_ts,
    rnk,
    amount
FROM Cte
WHERE rnk < 5

UNION ALL

SELECT
    customer_id,
    MIN(order_id),
    MIN(order_ts),
    MIN(rnk),
    SUM(amount)
FROM Cte
WHERE rnk >= 5
GROUP BY customer_id
ORDER BY customer_id;

*这适用于SQL Server

答案 2 :(得分:1)

尝试这样的事情,使用外部查询来获得结果

SELECT customer_id,(CASE WHEN ROW_NO <5 THEN ROW_NO ELSE 5 END) ROW_NO, SUM(amount) amount
FROM (
    SELECT customer_id, 
           order_id, 
           order_ts, 
           RANK() OVER (PARTITION BY customer_id ORDER BY order_ts ASC) ROW_NO, 
       amount 
FROM jq 
)   D
GROUP BY customer_id,(CASE WHEN ROW_NO <5 THEN ROW_NO ELSE 5 END)