【问题标题】:@ and := operator in SQLSQL 中的 @ 和 := 运算符
【发布时间】:2021-05-25 18:28:12
【问题描述】:

我正在处理一张桌子,我必须在其中找到会话之间的平均时间差。

我遇到了 2 个帖子,他们提供了以下解决方案。 Get average time between times in SQL

    SELECT  AVG(period)
FROM    (
        SELECT  TIME_TO_SEC(TIMEDIFF(@date_posted, date_posted)) AS period,
                @date_posted := date_posted
        FROM    (
                SELECT @date_posted := NULL
                ) vars,
                messages
        ORDER BY
                date_posted
        ) q

How to calculate the smallest period of time between consecutive events?

SELECT  (temperature - @r) AS diff,
        @r := temperature
FROM    (
        SELECT  @r := 0
        ) vars,
        temperatures
ORDER BY
        time

我发现很难理解查询结构来修改它以适应我的目的。有人可以把它分解成更简单的术语。通过基本的谷歌搜索,我认为 @var 是一些变量,您可以在其中插入值。我不知道 := 运算符。

感谢您的宝贵时间。

【问题讨论】:

  • 你使用的是 MySQL 还是 Postgresql?
  • 这感觉就像 mysql 与那些 @ 变量,但你有 postgresql 标记它不使用这样的变量。
  • 该链接没有解释 := 或 @var 实际在做什么。
  • @user-defined variable 前缀。 :=assigning operator (而不是 = 可以分配或比较,取决于上下文)。 我不知道总是先尝试一个想法来阅读文档。
  • 这两个例子都是错误的,因为它们在不同的表达式中分配和使用变量。也就是说,两者都使用窗口函数要容易得多。我建议你专注于学习窗口函数,而不是过时、不推荐和定制的变量方法。

标签: mysql sql


【解决方案1】:

正如其他人所描述的那样,@ 是一个变量,:= 用于赋值,让我试着澄清一下事情的进展情况。

查询以From 子句开头。第一个(包裹在括号中)就像一个带有别名结果的选择查询。这基本上是对名为@date_posted 的“变量”进行内联查询声明,并将其赋值为null。它使用“vars”作为表/别名要求中 sql 的简单别名。无论您包含多少个@variables(逗号分隔),它都只会返回一行,因此您永远不会遇到笛卡尔联接的问题。这就是为什么在第二部分的实际消息表之前有一个简单的逗号。

( SELECT @date_posted := NULL ) vars,

                

现在,查询的其余部分正在使用消息表,按 date_posted 排序。

现在选择 TIME_TO_SEC() 组件。这是计算@date_posted(当前读取第一条记录时为空)与 date_posted 之间的时间差,并按照您的预期存储在预期列“period”中。

第一次通过,为 NULL,第一条记录的时间段将是一个空答案,并且不应该扭曲最终平均值,因为空值被忽略了。现在它已经完成了该行的周期值的计算,它转到第二列并说取记录中“date_posted”中的任何值并将其分配给@date_posted 变量。所以现在你已经为所有后续记录启动了种子值。分配必须在计算之后完成,因此当它开始处理下一个记录时,它就像一个滞后(上一个记录)值。现在它将具有正确比较的日期。

只有在处理完所有记录后,它才能为您的结果获取周期的最终外部 AVG()。

这有帮助吗?

【讨论】:

    【解决方案2】:

    User variables 像这样使用是一个workaround 以在 Mysql 5.7 中缺少 window functions
    在这两个示例中,它们都专门提到了lag 功能。

    两个 SQL 语句相似,所以我只分析第一个。


    第一篇文章中的示例

    内部 FROM 子句

    ( SELECT @date_posted := NULL) vars, messages
    

    这是初始化。 @date_posted 获取初始 NULL 值。

    内部 SELECT 子句

    TIME_TO_SEC(TIMEDIFF(@date_posted, date_posted)) AS period, @date_posted := date_posted
    

    TIMEDIFF 中的@date_posted 保存前一行的 date_posted 值,并与该行中的 date_posted 进行比较以获得差异。然后分配当前行的 date_posted 值以进行到下一行。
    在第一行中,@date_posted 从初始化中获取 NULL 值。

    外部 SELECT FROM 子句

    将 AVG(平均)函数应用于计算周期列


    :=运营商

    引用手册...

    := 赋值运算符。使运算符左侧的用户变量采用其右侧的值。右侧的值可以是文字值、另一个存储值的变量或任何产生标量值的合法表达式,包括查询结果(前提是该值是标量值)。您可以在同一个 SET 语句中执行多个赋值。您可以在同一语句中执行多个赋值。
    与 = 不同,:= 运算符永远不会被解释为比较运算符。这意味着您可以在任何有效的 SQL 语句(不仅仅是 SET 语句)中使用 := 为变量赋值。

    【讨论】:

    • 真的很有见地。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多