![](/img/trans.png)
[英]MySQL: Self join table offset by one row (equiv to T-SQL CTE with ROW_NUMBER())
[英]How to self join a table and present a limited number of results, based on a passed criteria, in one row
我正在尝试创建一个作业预订报告,该报告将显示在特定日期创建的所有作业,然后是这些作业上每个项目#的最后三个作业(i-no),并在与作业相同的行中显示数据从特定日期开始。 如果没有以前的作业,则该字段将为null(当前为#NUM !,因为我们在Excel中手动进行此操作)。 如果只有一个先前的作业,则将填充相关字段,其余字段为null,依此类推。..我有一个作业表和jobheader表。 它们都包含非常相似的数据,除了两件事:作业表包含创建日期且不包含item#字段,而作业标题表包含项目编号但不包含创建日期字段。 (我正在努力获取包含所有内容的jobheader表,但是无论如何都必须找到该报告的解决方案。)这是我的表:
show CREATE TABLE job job CREATE TABLE `job` ( `job-no` varchar(12) DEFAULT NULL, `job-no2` int(11) DEFAULT NULL, `std-fix-cost` double DEFAULT NULL, `std-lab-cost` double DEFAULT NULL, `std-mat-cost` double DEFAULT NULL, `std-tot-cost` double DEFAULT NULL, `std-var-cost` double DEFAULT NULL, `create-date` date DEFAULT NULL, ) ENGINE=InnoDB DEFAULT CHARSET=utf8 show CREATE TABLE jobheader jobheader CREATE TABLE `jobheader` ( `sdate` date DEFAULT NULL, `qty` double DEFAULT NULL, `std-tot-cost` double DEFAULT NULL, `std-mat-cost` double DEFAULT NULL, `std-lab-cost` double DEFAULT NULL, `std-fix-cost` double DEFAULT NULL, `std-var-cost` double DEFAULT NULL, `i-no` varchar(30) DEFAULT NULL, `job-no2` int(11) DEFAULT NULL, `job-no` varchar(12) DEFAULT NULL, ) ENGINE=InnoDB DEFAULT CHARSET=utf8
这些表由job-no和job-no2连接。
这是我表中的数据:
job table: ║ job-no ║ job-no2 ║ std-fix-cost ║ std-lab-cost ║ std-mat-cost ║ std-tot-cost ║ std-var-cost ║ create-date ║ ║ 786993 ║ 0 ║ 177.2188 ║ 515.1117 ║ 1283.929 ║ 2346.3662 ║ 370.1067 ║ 4/04/2019 ║ ║ 787041 ║ 0 ║ 59.5367 ║ 70.8075 ║ 886.2611 ║ 1065.5539 ║ 48.9486 ║ 4/04/2019 ║ ║ 787041 ║ 1 ║ 103.475 ║ 123.0637 ║ 1067.8726 ║ 1379.4843 ║ 85.073 ║ 4/04/2019 ║ jobheader table: ║sdate║qty║std-tot-cost ║std-mat-cost║std-lab-cost║std-fix-cost║std-var-cost║i-no ║j2║job-no║ ║NULL ║200║ 1297.6372║ 942.9434║ 140.078 ║ 117.781 ║ 96.8348 ║NEOIN77886NX║1 ║734701║ ║NULL ║250║ 1230.327 ║ 918.7153║ 123.0637║ 103.475 ║ 85.073 ║NEOIN77886NX║3 ║762822║ ║NULL ║200║ 2346.3662║ 1283.929║ 515.1117║ 177.2188║ 370.1067║MEDV25653 ║0 ║786993║ ║NULL ║500║ 1065.5539║ 886.2611║ 70.8075 ║ 59.5367 ║ 48.9486 ║NEOIN77886NX║0 ║787041║
预期的输出(因为其中包含大量数据,所以会很混乱)。 我还附加了一张图像,以更好地表示我要寻找的内容。 在此处输入图片描述 :
║job-no║j2║create-date║i-no ║qty║sdate║std-tot-cost║std-mat-cost║std-lab-cost║std-fix-cost║std-var-cost║job-no║j2║Qty║std-tot-cost║std-mat-cost║std-lab-cost║std-fix-cost║std-var-cost║job-no║j2║Qty║std-tot-cost ║std-mat-cost║std-lab-cost║std-fix-cost║std-var-cost║job-no║j2 ║Qty ║std-tot-cost║std-mat-cost║std-lab-cost║std-fix-cost║std-var-cost║ ║787041║0 ║4/4/2019 ║NEOIN77886NX║200║ ║ 1,349.54║ 994.85 ║ 140.08 ║ 117.78 ║96.83 ║762822║3 ║250║ 1230.327║ 918.7153║ 123.0637║ 103.475 ║ 85.073 ║734701║1 ║200║ 1297.6372║ 942.9434║ 140.078 ║ 117.781 ║ 96.8348 ║#NUM! ║#NUM!║#NUM!║#NUM! ║#NUM! ║#NUM! ║#NUM! ║#NUM! ║ ║786993║0 ║4/4/2019 ║MEDV25653 ║200║ ║ 2,346.37║ 1,283.93║ 515.11 ║ 177.22 ║ 370.11 ║#NUM! ║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM! ║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║#NUM!║
以下是我的查询。 现在消除计算字段,它运行没有错误,对于昨天创建的每个作业,给我的结果太多了。 我将它们写为子查询,以便可以限制结果的数量,但是我似乎无法弄清楚如何将jobh.i-no传递到子查询中,因此不允许我限制结果。 如果我能弄清楚这一点,并对每个子查询都使用LIMIT1,LIMIT1,1和LIMIT 2,1,我认为这将满足我的需求。 关于如何更改查询或如何将Item#传递给子查询的任何建议?
select job.`job-no`, job.`job-no2`, job.`create-date`, jobh.`i-no`, jobh.qty, jobh.`start-date`, jobh.`std-tot-cost`, jobh.`std-mat-cost`, jobh.`std-lab-cost`, jobh.`std-fix-cost`, jobh.`std-var-cost`, tmp.`std-tot-cost` as PreviousJobStdTotCost, tmp.`std-mat-cost` as PreviousJobStdMatCost, tmp.`std-lab-cost` as PreviousJobStdLabCost, tmp.`std-fix-cost` as PreviousJobStdFixCost, tmp.`std-var-cost` as PreviousJobStdVarCost, tmp2.`std-tot-cost` as PreviousJob2StdTotCost, tmp2.`std-mat-cost` as PreviousJob2StdMaCost, tmp2.`std-lab-cost` as PreviousJob2StdLabCost, tmp2.`std-fix-cost` as PreviousJob2StdFixCost, tmp2.`std-var-cost` as PreviousJob2StdVarCost, tmp3.`std-tot-cost` as PreviousJob3StdTotCost, tmp3.`std-mat-cost` as PreviousJob3StdMatCost, tmp3.`std-lab-cost` as PreviousJob3StdLabCost, tmp3.`std-fix-cost` as PreviousJob3StdFixCost, tmp3.`std-var-cost` as PreviousJob3StdVarCost from asi.job as job left join asi.jobheader as jobh on job.`job-no`=jobh.`job-no` and job.`job-no2`=jobh.`job-no2` left join (select jobh1.`i-no`, jobh1.`job-no`, jobh1.`std-tot-cost`, jobh1.`std-mat-cost`, jobh1.`std-lab-cost`, jobh1.`std-fix-cost`, jobh1.`std-var-cost` from asi.jobheader as jobh1 order by jobh1.`job-no` desc) tmp on tmp.`i-no`=jobh.`i-no` and tmp.`job-no`not equal to jobh.`job-no` left join (select jobh2.`i-no`, jobh2.`job-no`, jobh2.`std-tot-cost`, jobh2.`std-mat-cost`, jobh2.`std-lab-cost`, jobh2.`std-fix-cost`, jobh2.`std-var-cost` from asi.jobheader as jobh2 order by jobh2.`job-no` desc ) tmp2 on tmp2.`i-no`=tmp.`i-no` and tmp2.`job-no` not equal to tmp.`job-no` left join (select jobh3.`i-no`, jobh3.`job-no`, jobh3.`std-tot-cost`, jobh3.`std-mat-cost`, jobh3.`std-lab-cost`, jobh3.`std-fix-cost`, jobh3.`std-var-cost` from asi.jobheader as jobh3 order by jobh3.`job-no` desc) tmp3 on tmp3.`i-no`=tmp2.`i-no` and tmp3.`job-no` not equal to tmp2.`job-no` where asi.job.`create-date`="2019-04-04" and asi.job.`job-no` is not null and asi.job.`job-no`""
好的,我认为这可能有效,但是我并不乐观。 我绝对怀疑它的执行速度会很快,但这是某件事。
select
job.`job-no`,
job.`job-no2`,
job.`create-date`,
jobh.`i-no`,
jobh.qty,
jobh.`start-date`,
jobh.`std-tot-cost`, jobh.`std-mat-cost`, jobh.`std-lab-cost`, jobh.`std-fix-cost`, jobh.`std-var-cost`,
tmp.`std-tot-cost` as PreviousJobStdTotCost, tmp.`std-mat-cost` as PreviousJobStdMatCost, tmp.`std-lab-cost` as PreviousJobStdLabCost, tmp.`std-fix-cost` as PreviousJobStdFixCost, tmp.`std-var-cost` as PreviousJobStdVarCost,
tmp2.`std-tot-cost` as PreviousJob2StdTotCost, tmp2.`std-mat-cost` as PreviousJob2StdMaCost, tmp2.`std-lab-cost` as PreviousJob2StdLabCost, tmp2.`std-fix-cost` as PreviousJob2StdFixCost, tmp2.`std-var-cost` as PreviousJob2StdVarCost,
tmp3.`std-tot-cost` as PreviousJob3StdTotCost, tmp3.`std-mat-cost` as PreviousJob3StdMatCost, tmp3.`std-lab-cost` as PreviousJob3StdLabCost,
tmp3.`std-fix-cost` as PreviousJob3StdFixCost, tmp3.`std-var-cost` as PreviousJob3StdVarCost
from asi.job as job
left join asi.jobheader as jobh on job.`job-no`=jobh.`job-no` and job.`job-no2`=jobh.`job-no2`
left join (
select jobh1.`std-tot-cost`, jobh1.`std-mat-cost`, jobh1.`std-lab-cost`, jobh1.`std-fix-cost`, jobh1.`std-var-cost`
from asi.jobheader as jobh1
where jobh1.`i-no`=jobh.`i-no` and jobh1.`job-no` < jobh.`job-no`
order by jobh1.`job-no` desc
limit 1
) tmp on 1=1
left join (
select jobh2.`std-tot-cost`, jobh2.`std-mat-cost`, jobh2.`std-lab-cost`, jobh2.`std-fix-cost`, jobh2.`std-var-cost`
from asi.jobheader as jobh2
where jobh2.`i-no`=tmp.`i-no` and jobh2.`job-no` < tmp.`job-no`
order by jobh2.`job-no` desc
limit 1
) tmp2 on 1=1
left join (
select jobh3.`std-tot-cost`, jobh3.`std-mat-cost`, jobh3.`std-lab-cost`, jobh3.`std-fix-cost`, jobh3.`std-var-cost`
from asi.jobheader as jobh3
where jobh3.`i-no`=tmp2.`i-no` and jobh3.`job-no` < tmp2.`job-no`
order by jobh3.`job-no` desc
limit 1
) tmp3 on 1=1
where asi.job.`create-date`="2019-04-04"
and asi.job.`job-no` is not null
and asi.job.`job-no`
但是,如果您可以在接收数据的最后进行一些处理,那么这可能是一个更好的解决方案:
select
job.`job-no`,
job.`job-no2`,
job.`create-date`,
jobh.`i-no`,
jobh.qty,
jobh.`start-date`, jobh.`std-tot-cost`, jobh.`std-mat-cost`, jobh.`std-lab-cost`, jobh.`std-fix-cost`, jobh.`std-var-cost`,
prev.`start-date` AS PreviousJobStartDate, prev.`std-tot-cost` as PreviousJobStdTotCost, prev.`std-mat-cost` as PreviousJobStdMatCost, prev.`std-lab-cost` as PreviousJobStdLabCost, prev.`std-fix-cost` as PreviousJobStdFixCost, prev.`std-var-cost` as PreviousJobStdVarCost
from asi.job as job
left join asi.jobheader as jobh on job.`job-no`=jobh.`job-no` and job.`job-no2`=jobh.`job-no2`
left join (
select jobh1.`start-date`, jobh1.`std-tot-cost`, jobh1.`std-mat-cost`, jobh1.`std-lab-cost`, jobh1.`std-fix-cost`, jobh1.`std-var-cost`
from asi.jobheader as jobh1
where jobh1.`i-no`=jobh.`i-no` and jobh1.`job-no` < jobh.`job-no`
order by jobh1.`job-no` desc
limit 3
) prev on 1=1
where asi.job.`create-date`="2019-04-04"
and asi.job.`job-no` is not null
and asi.job.`job-no`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.