简体   繁体   English

@ and:= 运算符在 SQL

[英]@ and := operator in SQL

I am working on a table where I have to find average time difference between sessions.我正在一张桌子上工作,我必须找到会话之间的平均时间差。

I came across 2 posts where they gave the following solutions.我遇到了 2 个帖子,他们提供了以下解决方案。 Get average time between times in SQL 获取 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

and

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

I am finding it difficult to understand the query structure to modify it to fit my purposes.我发现很难理解查询结构来修改它以适应我的目的。 Can someone please break it down into simpler terms.有人可以把它分解成更简单的术语。 With basic googling, I think @var is some variable where you insert values afterwards.通过基本的谷歌搜索,我认为 @var 是一些变量,您可以在其中插入值。 I have no idea about:= operator.我不知道:= 运算符。

I thank you for your time.我感谢你的时间。

As others described about the @ is a variable and := is for assignment, let me try to clarify the what and how things are going.正如其他人所描述的那样, @是一个变量, :=是用于赋值,让我试着澄清事情的进展情况和方式。

Query starts with the From clause.查询以From子句开始。 The first ( wrapped in parens ) is like a select query with an alias result.第一个(用括号括起来)就像一个带有别名结果的 select 查询。 This is basically doing an inline query declaration of a "variable" called @date_posted and assigning it a value null.这基本上是对名为@date_posted 的“变量”进行内联查询声明,并为其分配一个值null。 It uses "vars" as just a simple alias name for sql from table/alias requirement.它使用“vars”作为表/别名要求中 sql 的简单别名。 It will only ever return a single row no matter how many @variables you include (comma separated), so you'll never have an issue with a Cartesian Join.无论您包含多少个@variables(逗号分隔),它都只会返回一行,因此您永远不会遇到笛卡尔联接的问题。 That is why a simple comma before the actual table of messages in the second part.这就是为什么在第二部分的实际消息表之前有一个简单的逗号。

( SELECT @date_posted := NULL ) vars,

                

Now, the rest of the query is using the messages table, ordered by the date_posted.现在,查询的 rest 正在使用消息表,按 date_posted 排序。

Now the select TIME_TO_SEC() component.现在是 select TIME_TO_SEC() 组件。 This is computing whatever the time difference is between the @date_posted (currently null on first record read) and compares to date_posted and stores in expected column "period" as you would expect.这是计算@date_posted(当前为第一次读取记录时的 null)之间的时间差,并与 date_posted 进行比较,并按照您的预期存储在预期的列“period”中。

The first time through, being NULL, the period for the first record will be a null answer and should not skew the final average as nulls are left out.第一次通过,作为 NULL,第一条记录的周期将是 null 答案,并且不应扭曲最终平均值,因为空值被忽略。 Now that it has finished computing the period value for that row, it goes to the second column and says take whatever value is in the "date_posted" on the record and assign it to the @date_posted variable.现在它已经完成了该行的周期值的计算,它转到第二列并说取记录中“date_posted”中的任何值并将其分配给@date_posted 变量。 So now you have the seed value started for all subsequent records.所以现在你已经为所有后续记录启动了种子值。 The assignment has to be done AFTER the calculation so it acts like a lag (previous record) value when it starts the next record for processing.分配必须在计算之后完成,因此当它开始处理下一个记录时,它就像一个滞后(上一个记录)值。 Now it will have the date to properly compare against.现在它将具有正确比较的日期。

Only after all records are processed can it then take the final outer AVG() of the period for your results.只有在处理完所有记录后,它才能为您的结果获取该期间的最终外部 AVG()。

Does that help?这有帮助吗?

User variables used like this are a workaround to the lack of window functions in Mysql 5.7.像这样使用的User variables是 Mysql 5.7 中缺少window functions解决方法
In both examples they refer specifically to the lag feature.在这两个示例中,它们都专门提到了lag功能。

Both SQL sentences are similar so I will be analyzing only the first one.两个 SQL 句子相似,所以我将只分析第一个。


Example from first post第一篇文章的例子

Inner FROM clause内部 FROM 子句

( SELECT @date_posted := NULL) vars, messages

This is the inicialization.这就是初始化。 @date_posted gets an initial NULL value. @date_posted 获取初始 NULL 值。

Inner SELECT clause内 SELECT 子句

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

@date_posted inside TIMEDIFF holds previous row's value of date_posted and is compared against date_posted from this row to get the difference. TIMEDIFF 中的@date_posted 保存前一行的 date_posted 值,并与该行中的 date_posted 进行比较以获得差异。 Then is assigned current's row date_posted value to carry on to the next row.然后分配当前行的 date_posted 值以进行到下一行。
In first row @date_posted gets the NULL value from initialization.在第一行 @date_posted 从初始化中获取 NULL 值。

Outer SELECT FROM clause外 SELECT FROM 子句

Applies AVG (Average) function to the calculated period column将 AVG (Average) function 应用于计算周期列


:= operator :=运算符

Quoting the manual...引用手册...

:= Assignment operator. :=赋值运算符。 Causes the user variable on the left hand side of the operator to take on the value to its right.使运算符左侧的用户变量采用其右侧的值。 The value on the right hand side may be a literal value, another variable storing a value, or any legal expression that yields a scalar value, including the result of a query (provided that this value is a scalar value).右侧的值可以是文字值、另一个存储值的变量或任何产生标量值的合法表达式,包括查询结果(前提是该值是标量值)。 You can perform multiple assignments in the same SET statement.您可以在同一个 SET 语句中执行多个赋值。 You can perform multiple assignments in the same statement.您可以在同一语句中执行多个赋值。
Unlike =, the:= operator is never interpreted as a comparison operator.与 = 不同,:= 运算符永远不会被解释为比较运算符。 This means you can use:= in any valid SQL statement (not just in SET statements) to assign a value to a variable.这意味着您可以在任何有效的 SQL 语句(不仅仅是在 SET 语句中)中使用:= 为变量赋值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM