【问题标题】:Update with SUM and LIMIT, rolling SUM使用 SUM 和 LIMIT 更新,滚动 SUM
【发布时间】:2013-10-14 00:38:43
【问题描述】:

我有 2 张桌子,SVISEOVERW

OVERW 里面,我有一些带有人员 ID 和得分日期的分数。 例如

p_id    degrees    mo_date
5        10.2      2013-10-09
5        9.85      2013-03-10
8        14.75     2013-04-25
8        11.00     2013-02-22
5        5.45      2013-08-11
5        6.2       2013-06-10

SVISE.ofh 字段必须更新为最后三个记录的总和 (对于特定的人,按日期降序排列),因此对于 id 为 5 的人,总和将来自行

5        10.2      2013-10-09
5        5.45      2013-08-11
5        6.2       2013-06-10

sum=21.85.

希望的最终结果SVISE 上,基于上述值:

HID OFH     START
5   21.85   October, 16 2013   ##(10.2 + 5.45 + 6.2)
5   21.5    September, 07 2013 ##(5.45 + 6.2 + 9.85)
5   0       March, 05 2013     ##(no rows)
8   25.75   October, 14 2013   ##(14.75 + 11)
3   0       October, 14 2013   ##(no rows)
5   0       March, 05 2012     ##(no rows)

OFH最初为 0



我可以获得特定人的总和,但我不能使用 limit 来获取最后 3 行。它会被忽略。

这是我用来检索给定日期每人所有学位的总和的查询:

UPDATE SVISE SV
SET 
SV.ofh=(SELECT sum(degrees) FROM OVERW WHERE p_id =SV.hid 
AND date(mo_date)<date(SV.start) 
AND year(mo_date)=year(SV.start))

我不能只对 sum 使用 limit:

UPDATE SVISE SV
SET 
SV.ofh=(SELECT sum(degrees) FROM OVERW WHERE p_id =SV.hid 
AND date(mo_date)<date(SV.start) 
AND year(mo_date)=year(SV.start)
ORDER BY mo_date DESC 
LIMIT 3)

这不起作用。

我已经尝试使用multi-table updatesnested queries 来实现这一点。 每个场景都有已知的限制,阻碍我完成预期的结果。

  • 嵌套查询无法查看父表。 Unknown column 'SV.hid'in 'where clause'
  • 多表更新不能与限制一起使用。 Incorrect usage of UPDATE and LIMIT

任何解决方案都可以。无需在单个查询中执行此操作。如果有人想尝试使用中间表。

SQL fiddle 也可用。

提前感谢您的帮助。

--更新--

这是来自 Akash 的解决方案:http://sqlfiddle.com/#!2/4cf1a/1

【问题讨论】:

  • 在您的查询中,您正在验证年份是否匹配。这是要求的一部分吗?此外,哪些列或哪些列构成SVISE(或svice,根据SQL Fiddle)的主键?
  • @AndriyM,我想要一个人的“最后”3 度,唯一的过滤器是日期。从现在起最后 3 度或从昨天起最后 3 度等。
  • 这个数据集是否与sqlfiddle中提供的对应?如果没有,请考虑为该 sqlfiddle 数据集提供正确的结果集,并相应地更新您的问题。只为 overw 表提供完整的结果集是明智的。
  • 另外,你确定这些应该是 FLOAT 而不是 DECIMAL?
  • 嗨草莓,是的,它是相同的数据集,我将小数更改为浮点数只是为了让人们更容易从视觉上理解它,以及一些随机数据。小提琴结构是一样的,你可以改变它,插入你喜欢的任何行,甚至让它包含与问题相同的行。

标签: mysql sql-update


【解决方案1】:

这应该可行,

更新加入svice

UPDATE
svice SV
JOIN (
  SELECT 
    hid,
    start,
    sum(degrees) as degrees
  FROM 
    (
      SELECT 
        *,
        IF(@prev_row <> unix_timestamp(start)+P_ID, @row_number:=0,NULL),
        @prev_row:=unix_timestamp(start)+P_ID,
        @row_number:=@row_number+1 as row_number
      FROM 
        (
        SELECT
          mo_date,
          p_id,
          hid,
          start,
          degrees
        FROM 
          OVERW 
          JOIN svice sv ON ( p_id = hid 
                            AND date(mo_date)<date(SV.start) 
                            AND year(mo_date)=year(SV.start) )
         ORDER BY
          hid,
          start,
          mo_date desc
        ) sub_query1
        JOIN ( select @row_number:=0, @prev_row:=0 ) sub_query2
      ) sub_query
    where
      row_number <= 3
    GROUP BY 
      hid,
      start
  ) sub_query ON ( sub_query.hid = sv.hid AND sub_query.start = sv.start )
SET 
  SV.ofh = sub_query.degrees

注意:请检查您的更新数据,由于日期条件,提供的测试数据无法产生您预期的结果

【讨论】:

  • 谢谢,但我需要使用日期过滤器。我需要在 ORDER BY 之前使用“WHERE date(mo_date)
  • 如果每个svice记录有一个overw p_id记录对应的记录,你可以直接在最里面的查询中做一个join
  • SVISE 表是否每个 p_id 都有一个条目?
  • 在每一行中,SVICE 表都有一个日期,基于该日期和隐藏我需要为SVICE 的每一行找到OVERW 3 度的总和。跨度>
  • 但是SVISE 表中的每个overw p_id 是否只有一个条目?
【解决方案2】:

试试

UPDATE svice SV
JOIN (SELECT SUM(degrees)sumdeg,p_id FROM(SELECT DISTINCT degrees,p_id FROM OVERW,svice WHERE OVERW.p_id IN (SELECT svice.hid FROM svice) 
AND date(mo_date)<date(svice.start) 
AND year(mo_date)=year(svice.start)ORDER BY mo_date DESC )deg  group by p_id)bbc 
      ON bbc.p_id=SV.hid 
      SET 
SV.ofh=bbc.sumdeg where p_id =SV.hid 

http://sqlfiddle.com/#!2/95b42/42

越来越近,现在它“只”需要在 GROUP BY 中进行限制。

【讨论】:

  • 米海,我已经设置了一个小提琴。我已经在我的问题中粘贴了小提琴链接。你会注意到结果值是错误的
  • sqlfiddle.com/#!2/64d96/1 我无法更新所有行,需要更懂行的人。
  • 非常感谢您的努力
【解决方案3】:

两个假设:

  1. 您可以弄清楚如何将其转化为更新,并且
  2. PK 存在于 (id,mo_date)

那么你就可以这样做了——

SELECT p_id
     , SUM(degrees) ttl
  FROM 
     ( SELECT x.*
         FROM overw x 
         JOIN overw y 
           ON y.p_id = x.p_id 
          AND y.mo_date >= x.mo_date 
        GROUP 
           BY p_id
            , mo_date HAVING COUNT(*) <= 3
     ) a 
 GROUP 
    BY p_id;

【讨论】:

  • 在这里试一试:sqlfiddle.com/#!2/64d96/1
  • 草莓,结果不应该分组,检查我的问题中的“期望结果”
【解决方案4】:

也许我的速度很慢,但现在让我们先忽略 svice。 你能显示正确的结果和下面每一行的工作吗...

+------+---------+------------+--------+
| p_id | degrees | mo_date    | result |
+------+---------+------------+--------+
|    5 |    6.20 | 2013-06-10 |      ? | 
|    5 |    5.45 | 2013-08-11 |      ? |
|    5 |   10.20 | 2013-10-09 |  21.85 | <- = 10.2+5.45+6.2 = 21.85 
|    8 |   14.75 | 2013-04-25 |      ? |
|    5 |    9.85 | 2013-03-10 |      ? |
|    8 |   11.00 | 2013-02-22 |      ? |  
+------+---------+------------+--------+

【讨论】:

  • 这没有意义。之前,您能够获得上面第 3 行的 10.2+5.45+6.2 = 21.85 的中间结果,而无需参考任何其他表格。
  • 这里草莓,我已经插入了你的数据,所以你可以用 Akash 的解决方案检查它
  • 似乎 SQLFiddle 已关闭!
猜你喜欢
  • 2014-07-27
  • 2021-01-18
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多