I have a table in mysql database this data.
id date number qty
114 07-10-2018 200 5
120 01-12-2018 300 10
123 03-02-2019 700 12
1126 07-03-2019 1000 15
I want to calculate difference between two consecutive rows and i need output format be like:
id date number diff qty avg
114 07-10-2018 200 0 5 0
120 01-12-2018 300 100 10 10
123 03-02-2019 700 400 12 33.33
1126 07-03-2019 1000 300 15 20
有人知道如何在mysql查询中执行此操作吗?我希望diff和avg列的第一个值为0,其余为差异。
答案 0 :(得分:5)
对于 MySQL 8 ,然后使用Lag窗口功能。
19/08/22 21:26:06 ERROR Executor: Exception in task 3.0 in stage 0.0 (TID 3)
com.amazonaws.services.kinesisfirehose.model.AmazonKinesisFirehoseException: 1 validation error detected: Value '[]' at 'records' failed to satisfy constraint: Member must have length greater than or equal to 1 (Service: AmazonKinesisFirehose; Status Code: 400; Error Code: ValidationException; Request ID: c91aea46-66de-013c-9cc3-e0e862cbc37c)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1695)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1350)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1101)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:758)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:732)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:714)
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:674)
at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:656)
at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:520)
at com.amazonaws.services.kinesisfirehose.AmazonKinesisFirehoseClient.doInvoke(AmazonKinesisFirehoseClient.java:1179)
at com.amazonaws.services.kinesisfirehose.AmazonKinesisFirehoseClient.invoke(AmazonKinesisFirehoseClient.java:1148)
at com.amazonaws.services.kinesisfirehose.AmazonKinesisFirehoseClient.invoke(AmazonKinesisFirehoseClient.java:1137)
at com.amazonaws.services.kinesisfirehose.AmazonKinesisFirehoseClient.executePutRecordBatch(AmazonKinesisFirehoseClient.java:871)
at com.amazonaws.services.kinesisfirehose.AmazonKinesisFirehoseClient.putRecordBatch(AmazonKinesisFirehoseClient.java:842)
at com.siriusxm.kafka_kinesis.KafkaKinesisStructureStreamingBatch$1.close(KafkaKinesisStructureStreamingBatch.java:118)
at org.apache.spark.sql.execution.streaming.ForeachSink$$anonfun$addBatch$1.apply(ForeachSink.scala:60)
at org.apache.spark.sql.execution.streaming.ForeachSink$$anonfun$addBatch$1.apply(ForeachSink.scala:49)
at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$29.apply(RDD.scala:935)
at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$29.apply(RDD.scala:935)
at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:2074)
at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:2074)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
at org.apache.spark.scheduler.Task.run(Task.scala:109)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
对于MySQL 5.7或更低版本
我们可以使用MySQL variable来完成这项工作。考虑您的表名是“ test”。
if (isset($_POST['signin'])) {
$uname=$_POST['username'];
$password=md5($_POST['password']);
$sql ="SELECT * FROM users WHERE username=:uname and Password=:password";
$run_guest= $dbh -> prepare($sql);
$query-> bindParam(':uname', $uname, PDO::PARAM_STR);
$query-> bindParam(':password', $password, PDO::PARAM_STR);
$query-> execute();
$results=$query->fetchAll(PDO::FETCH_OBJ);
if($query->rowCount() > 0)
{
foreach ($results as $result) {
$status=$result->Status;
$role = $result->Role;
$_SESSION['uid']=$result->id;
}
if($status==0)
{
$msg="Your account is Inactive. Please contact admin";
}
if($role='Guest'){
$_SESSION['gtlogin']=$_POST['username'];
echo "<script type='text/javascript'> document.location = 'changepassword.php'; </script>";
}
if($role='Staff'){
$_SESSION['stlogin']=$_POST['username'];
echo "<script type='text/javascript'> document.location = 'staff/dashboard.php'; </script>";
}
if($role='Admin'){
$_SESSION['alogin']=$_POST['username'];
echo "<script type='text/javascript'> document.location = 'admin/changepassword.php'; </script>";
}
}
else{
echo "<script>alert('Invalid Details');</script>";
}
说明:
SELECT
test.id,
test.date,
test.number,
test.qty,
IFNULL(test.number - LAG(test.number) OVER w, 0) AS diff,
ROUND(IFNULL(test.number - LAG(test.number) OVER w, 0)/ test.qty, 2) AS 'Avg'
FROM purchases test
WINDOW w AS (ORDER BY test.`date` ASC);
我们在FROM子句中将变量 @prev_number 初始化为零,并与 test 表的每一行连接。 MySQL Query:
SELECT
test.id,
test.date,
test.number,
test.qty,
@diff:= IF(@prev_number = 0, 0, test.number - @prev_number) AS diff,
ROUND(@diff / qty, 2) 'avg',
@prev_number:= test.number as dummy
FROM
test,
(SELECT @prev_number:= 0 AS num) AS b
ORDER BY test.`date` ASC;
-------------------------------------------------------------------------------
Output:
| id | date | number| qty | diff | avg | dummy |
-----------------------------------------------------------------
| 114 | 2018-10-07 | 200 | 5 | 0 | 0.00 | 200 |
| 120 | 2018-12-01 | 300 | 10 | 100 | 10.00 | 300 |
| 123 | 2019-02-03 | 700 | 12 | 400 | 33.33 | 700 |
| 1126 | 2019-03-07 | 1000 | 15 | 300 | 20.00 | 1000 |
首先,我们生成差异,然后创建另一个变量 diff ,以将其重新用于平均计算。我们还加入了一个条件,以使第一行的差异为零。(SELECT @prev_number:= 0 AS num) AS b
,我们正在为此变量设置当前 number ,以便下一行可以使用。注意:我们必须首先在“ 差异”和“ 平均值”中使用此变量,然后将其设置为新值,因此下一行可以访问上一行的值。
您可以根据需要跳过/修改order by子句。
答案 1 :(得分:1)
可能会有更好的方法,但是请尝试以下方法:
SELECT A.id,
A.date,
A.number,
A.qty,
A.diff,
B.avg
FROM
(SELECT *, abs(LAG(number, 1, number) OVER (ORDER BY id) - number) AS 'diff'
FROM table) AS A
JOIN
(SELECT *, abs(LAG(number, 1, number) OVER (ORDER BY id) - number)/qty AS 'avg' FROM table) AS B
ON A.id = B.id;