一个函数

时间:2018-05-15 19:03:15

标签: php sql database postgresql

我需要在postgresql数据库的单个SQL查询中返回多个值。这是我到目前为止的查询:

SELECT AVG("percent"), MIN("percent"), MAX("percent"), AVG("profit"), MIN("profit"), MAX("profit")
FROM public.log_analyticss 
WHERE "buyPlatform" = 'platA' AND
"date" >= '1526356073.6126819'

数据

date             sellPlatform     profit      percent    
----------       ------------     ----------  ----------
1526356073.61    platA            0           10.1
1526356073.62    platA            22          11
1526356073.63    platA            3           7
1526356073.64    platA            1           8
1526356073.65    platA            11          9
1526356073.66    platA            12          10
1526356073.67    platA            13          15

期望的结果

date             sellPlatform     profit      percent    
----------       ------------     ----------  ----------
1526356073.61    platA            0           10.1         //MIN Profit
1526356073.62    platA            22          11           //MAX Profit
1526356073.63    platA            3           7            //MIN Perc
1526356073.67    platA            13          15           //MAX Perc

//然后以某种方式我希望它返回AVG,如果这是可能的。否则,我不介意运行另一个查询来执行此操作。

问题是我不想要MIN和MAX值。我想要从中获取MIN和MAX值的整行数据。

我知道我要求AVG和MIN / MAX值,它将以两种不同的格式返回数据。我知道这可能是不可能的。但任何有关如何最有效地做到这一点的帮助将是非常有帮助的。

现在我只是将整个数据集拉入我的代码并计算我的代码中的平均值,最小值和最大值,我知道这非常糟糕且非常慢。该表有大约800万行,我抓取的数据集大约是9000行,所以它现在的方式非常慢。

3 个答案:

答案 0 :(得分:1)

检索与最小值/最大值关联的行的最有效方法通常不涉及MIN() / MAX()聚合;相反,您只需在查询中附加ORDER BY,然后添加LIMIT 1即可获取第一条记录。

这意味着您需要四个SELECT语句,其中包含四种不同的排序,但您可以将昂贵的部分(从log_analyticss获取)分解为temp table或{{3} },例如:

WITH Data AS (
  SELECT *
  FROM public.log_analyticss 
  WHERE "buyPlatform" = 'platA' AND
    "date" >= '1526356073.6126819'
)
(SELECT 'Min percent', * FROM Data ORDER BY "percent" ASC LIMIT 1)
UNION ALL
(SELECT 'Max percent', * FROM Data ORDER BY "percent" DESC LIMIT 1)
UNION ALL
(SELECT 'Min profit', * FROM Data ORDER BY "profit" ASC LIMIT 1)
UNION ALL
(SELECT 'Max profit', * FROM Data ORDER BY "profit" DESC LIMIT 1)

在您的情况下,临时表可能比CTE更好,因为您可以重新使用它来计算平均值。

请注意,如果其中一个最大/最小值由两个不同的行共享,则此查询将仅返回其中一个。所选行是随机有效选择的,但您可以将更多字段附加到ORDER BY子句以作为打破平局。

如果在这种情况下你真的想要两个记录,你需要更像Auston或Radim的答案,即首先计算聚合,然后再加入profitpercent的数据列。您仍然可以在此处使用临时表/ CTE,以避免多次点击log_analyticss

答案 1 :(得分:0)

我认为最好的方法是通过两个查询: 第一个检索指标,就像你所做的那样; 第二个查询检索样本寄存器。

或者您可以尝试运行临时表(在结束会话后自动删除):

CREATE TEMP TABLE statistics AS 
    SELECT AVG(percent) as perc_avg, MIN(percent) as perc_avg, MAX(percent) as perc_max, AVG(profit) as pro_avg, MIN(profit) as pro_min, MAX(profit) as pro_max
    FROM public.log_analyticss 
    WHERE buyPlatform = 'platA' AND
    sellPlatform = 'platB' AND 
    productId = '183948' AND
    date >= '1526356073.6126819'
;
    SELECT date, sellPlatform, profit, percent
    FROM public.log_analyticss a join statistics s
     on (a.profit = s.pro_max or a.profit = s.pro_min or
         a.percent = s.perc_max or a.percent = s.perc_min)
    WHERE buyPlatform = 'platA' AND
    sellPlatform = 'platB' AND 
    productId = '183948' AND
    date >= '1526356073.6126819';

对临时表的引用: http://www.postgresql.org/docs/9.2/static/sql-createtable.html

答案 2 :(得分:0)

你需要这些内容:

SELECT a.*
FROM public.log_analyticss  a
JOIN
(
    SELECT 
        MIN("percent") min_percent, 
        MAX("percent") max_percent, 
        MIN("profit") min_profit, 
        MAX("profit") max_profit
    FROM public.log_analyticss 
) t ON a.date = t.date AND
       a.sellPlatform = t.sellPlatform AND
       (a.profit = minprofit OR
        a.profit = maxprofit OR
        a.percent = minpercent OR
        a.percent = maxpercent)