GROUP BY 的替代方法,当 WINDOW 无法正常工作时.. SQL

Alternative to GROUP BY, when a WINDOW isn't working properly.. SQL

我觉得这是一个简单的答案,但我似乎无法正确回答..

最初我 运行 有两个查询,因为我不知道如何一次解决这个问题。这是我最初 table "free2" 的查询:

WITH prep AS (
        SELECT *,
            (((odds - 1)/div) + 1) AS ew_odds,
            (odds*size) AS possible_win_returns,
            (((odds - 1)/div) + 1)*size AS possible_ew_returns
        FROM scratch.free
    ),

    prof AS(
        SELECT *,
            (possible_ew_returns+possible_win_returns) AS possible_total_win,
            (possible_win_returns*win) - size AS win_profit,
            (possible_ew_returns*places) - size AS ew_profit
        FROM prep 
    )

    SELECT 
        date_trunc(prof.date, DAY) AS DAY,
        SUM(ew_odds) AS ew_odds,
        SUM(size) AS size,
        SUM(odds) AS odds,
        SUM(places) AS places,
        SUM(div) AS divisor,
        SUM (total_size) AS total_size,
        SUM(won) AS profit,
        SUM(ew_profit) AS ew_prof,
        SUM(win_profit) AS win_prof,
        SUM(possible_total_win) AS pos_tot_win,
        SUM(possible_ew_returns) AS pos_ew_ret,
        SUM(possible_win_returns) AS pos_win_ret
    FROM prof
    GROUP BY 1
    ORDER BY day DESC

它按天对我所有的总和进行了分组,这就是我想要做的。然后我通过 运行 第二个查询将第二个 table 加入到第一个中:

SELECT d.*,
    f.ew_odds,
    f.size,
    f.odds,
    f.places,
    f.divisor,
    f.total_size,
    f.profit,
    f.ew_prof AS ew_profit,
    f.win_prof AS win_profit,
    f.pos_tot_win AS possible_total_win,
    f.pos_ew_ret AS possible_ew_returns,
    f.pos_win_ret AS possible_win_returns,
    date_trunc(d.day, week) AS week,
    date_trunc(d.day, month) AS month,
    date_trunc(d.day, year) AS year,
    date_trunc(d.day, quarter) AS quarter
FROM scratch.free2 AS f
LEFT JOIN accounts.daily_movement AS d 
    ON d.day = f.day

正如我所说,效果很好。但是,我需要在一个查询中将其作为一个整体进行复制。我不能直接这样做,因为 GROUP BY 子句会干扰 LEFT JOIN。所以我试着把所有第一个table的值,一个window函数:

prof AS (
    SELECT *,
        (possible_ew_returns+possible_win_returns) AS possible_total_win,
        (possible_win_returns*win) - size AS win_profit,
        (possible_ew_returns*places) - size AS ew_profit,
        date_trunc(date, DAY) AS day
    FROM calculations 
)

sum AS (
    SELECT prof.day,
    SUM(prof.ew_odds) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS ew_odds,
    SUM(prof.size) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS size,
    SUM(prof.odds) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS odds,
    SUM(prof.places) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
        AS places,
    SUM(prof.div) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS divisor,
    SUM(prof.total_size) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS total_size,
    SUM(prof.won) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS won,
    SUM(prof.rico) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS rico,
    SUM(prof.won) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS profit,
    SUM(prof.ew_profit)
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS ew_prof,
    SUM(prof.win_profit) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS win_prof,
    SUM(prof.possible_total_win) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS possible_tot_win,
    SUM(prof.possible_ew_returns) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS possible_ew_returns,
    SUM(prof.possible_win_returns) 
        OVER (PARTITION BY prof.day RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
        AS possible_win_returns
    FROM prof)

SELECT 
    sum.*
    d.total_euros,
    d.profit_bf_exp,
    d.percentage_profit,
    d.profit_aft_exp,
    d.brendan_profit,
    d.brendan_transactions,
    d.brendan_daily,
    d.brendan_percentage,
    d.michael_profit,
    d.michael_transactions,
    d.michael_daily,
    d.michael_percentage,
    d.general_expenses,
    d.thiago_payment,
    d.pedro_payment,
    d.rodrigues_payment,
    d.felipe_payment,
    d.expenses_notes,
    d.details
FROM sum
LEFT JOIN accounts.daily_movement AS d ON d.day = sum.day
ORDER BY sum.day DESC

我尝试将每个 WINDOW 的 RANGE 更改为 ROWS.. 但它仍然是错误的。

发生的事情是每天的所有分组都没有正确发生,它显示日期是单数,每个值的总和相同,但是会有大约 10-20 行完全相同的 SUMS 和 DAYs 数据..

"size" 列和 "day DESC" 的前 5 行应该如下所示:

Row day size
1 2017-04-30 1679.27
2 2017-04-29 7292.809999999996
3 2017-04-28 3247.04
4 2017-04-27 2209.2000000000003
5 2017-04-26 2932.42

但是,结果是这样的:

Row day size
1 2017-04-30 1679.27
2 2017-04-30 1679.27
3 2017-04-30 1679.27
4 2017-04-30 1679.27
5 2017-04-30 1679.27

如何防止数据中的 SUM 和日期重复?

Which as I said, worked fine. However, I need to replicate this as a whole in one query...

尝试以下(对于 BigQuery StandardSQL)

这只是简单地将您的两个步骤合二为一!
如果像您所说的那样,它们分别为您工作 - 下面的内容也必须为您工作!

#standardSQL
WITH prep AS (
  SELECT *,
    (((odds - 1)/DIV) + 1) AS ew_odds,
    (odds*size) AS possible_win_returns,
    (((odds - 1)/DIV) + 1)*size AS possible_ew_returns
  FROM scratch.free
),
prof AS(
  SELECT *,
    (possible_ew_returns+possible_win_returns) AS possible_total_win,
    (possible_win_returns*win) - size AS win_profit,
    (possible_ew_returns*places) - size AS ew_profit
  FROM prep 
),
free2 AS (
  SELECT 
    DATE_TRUNC(prof.date, DAY) AS DAY,
    SUM(ew_odds) AS ew_odds,
    SUM(size) AS size,
    SUM(odds) AS odds,
    SUM(places) AS places,
    SUM(DIV) AS divisor,
    SUM (total_size) AS total_size,
    SUM(won) AS profit,
    SUM(ew_profit) AS ew_prof,
    SUM(win_profit) AS win_prof,
    SUM(possible_total_win) AS pos_tot_win,
    SUM(possible_ew_returns) AS pos_ew_ret,
    SUM(possible_win_returns) AS pos_win_ret
  FROM prof
  GROUP BY 1
)
SELECT d.*,
  f.ew_odds,
  f.size,
  f.odds,
  f.places,
  f.divisor,
  f.total_size,
  f.profit,
  f.ew_prof AS ew_profit,
  f.win_prof AS win_profit,
  f.pos_tot_win AS possible_total_win,
  f.pos_ew_ret AS possible_ew_returns,
  f.pos_win_ret AS possible_win_returns,
  DATE_TRUNC(d.day, week) AS week,
  DATE_TRUNC(d.day, month) AS month,
  DATE_TRUNC(d.day, year) AS year,
  DATE_TRUNC(d.day, quarter) AS quarter
FROM free2 AS f
LEFT JOIN accounts.daily_movement AS d 
ON d.day = f.day