SELECT SomeColumn其中任何N行或更少行的SUM(SomeOtherColumn)是某个值

时间:2016-05-29 05:52:26

标签: mysql

我完全被这个技能评估问题困扰了。技能评估已完成。我太老了,不能用SO欺骗我的方式......只是好奇如何解决这个问题。

您有一个包含以下列的表:

#include <iostream>
#include <string.h>

using namespace std;

char* getCoordinates(char* AndroidID)
{//Access the database and get the South Latitude value
    //This is here is dummy data for testing
    const char* S = "27.19122859";
    const char* N = "27.19245011";
    const char* W = "31.17657602";
    const char* E = "31.17657602";
    char X[100]="";
    strncat(X, "S", 1);
    strncat(X, S, strlen(S));
    strncat(X, "N", 1);
    strncat(X, N, strlen(N));
    strncat(X, "W", 1);
    strncat(X, W, strlen(W));
    strncat(X, "E", 1);
    strncat(X, E, strlen(E));
    char* Y = X;
    return Y;
}

int main()
{
    char* sda=NULL;
    char* T=getCoordinates(sda);
    cout<<T;
    return 0;
}

您如何选择所有收件人,每个收件人的金额大于或等于X?

例如:

Sender | Recipient | Date | Amount

如果X = $ 1024,你应该得到Jane,Vivian和Josh。 Josh,因为$ 500 + $ 500 + $ 150&gt; $ 1024

所有三种解决方案都有效。非常感谢你们。真的很感激。

选择@Tim Biegeleisen对简单因素的回答。

4 个答案:

答案 0 :(得分:3)

一个可行的技巧是为每个Amount生成每个recipient的行号。然后,我们可以使用简单的WHERE条件简单地限制每组的最大三个金额。

SELECT Recipient, SUM(Amount)
FROM test t
WHERE (SELECT 1 + COUNT(*)
     FROM test
     WHERE Amount >= t.Amount AND Recipient = t.Recipient AND
           date < t.date) <= 3
GROUP BY Recipient
HAVING SUM(Amount) >= 1024

此解决方案使用交易日期来打破关系(例如,在Josh收到两个不同记录中的500美元的情况下)。该解决方案对于在同一天具有相同金额的两个交易的接收者的使用情况不稳健。这个解决方案的一个好处是它不需要使用任何用户定义的变量。

SQLFiddle

答案 1 :(得分:2)

您可以使用变量按降序数量的顺序对每个接收者的记录进行编号,然后过滤那些收到的数字不超过3的记录:

select   receiver,
         sum(amount)
from    (select   @num := if(@rec = receiver, @num + 1, 1) as rn,
                  @rec := receiver as receiver,
                  amount
         from     transaction
         order by receiver,
                  amount desc) as numbered
where    rn <= 3
group by receiver
having   sum(amount) >= 1024

SQL fiddle

这个解决方案的优点是它使用变量来避免基表被查询两次,这对大型数据集会产生巨大的性能影响。

此外,它保证每个接收者最多返回3条记录,即使在第三方也会有一个平局:你永远不会得到4。

答案 2 :(得分:1)

你能做的就是抓住每个收件人的前3名。如果他们的金额大于设定的限额,那么你可以返回他们的名字

SET @x = 1024;
SELECT t.Recipient
FROM (
    SELECT 
      Sender, 
      Recipient, 
      Amount, 
      SUM(Amount) as total_amount,
      @count := if(@rec = Recipient, @count + 1, 1) as counter,
      @rec := Recipient
  FROM test
  CROSS JOIN (SELECT @count := 1, @rec := '') t
  GROUP BY Recipient
  HAVING counter <= 3
  ORDER BY Recipient, Amount desc
) t
WHERE t.total_amount >= @x;

<强> FIDDLE

答案 3 :(得分:-2)

;
WITH cte
AS (SELECT
  t.amount,
  t.recipient,
  1 AS cnt
FROM transfers t
UNION ALL
SELECT
  t1.amount + t2.amount,
  t2.recipient,
  cnt + 1
FROM cte t2
INNER JOIN transfers t1
  ON t1.recipient = t2.recipient
  AND t1.amount + t2.amount <= 1024
WHERE cnt <= 2)
SELECT
  *
FROM cte
WHERE amount >= 1024