jho*_*owe 10 sql t-sql sql-server sql-server-2012
这篇文章是继续基于条件的另一个post sql select min或max的问题
我试图根据各种条件得到一排.
场景1 -如果没有小时存在(setup+ processtime> 0),则获得最高行.
场景2 -如果有几个小时(如本例所示oprnum)在此号码后显示下一个操作().(这将是60英寸prodroute).
查询需要在CTE中工作,因为它是更大查询的一部分.
CREATE TABLE ProdRoute
([ProdId] varchar(10), [OprNum] int, [SetupTime] int, [ProcessTime] numeric)
;
INSERT INTO ProdRoute
([ProdId], [OprNum], [SetupTime], [ProcessTime])
VALUES
('12M0004893', 12, 0.7700000000000000, 1.2500000000000000),
('12M0004893', 12, 0.0000000000000000, 0.0000000000000000),
('12M0004893', 40, 0.0800000000000000, 0.4000000000000000),
('12M0004893', 50, 0.0400000000000000, 2.8000000000000000),
('12M0004893', 50, 0.0000000000000000, 0.0000000000000000),
('12M0004893', 60, 0.0000000000000000, 0.6100000000000000),
('12M0004893', 60, 0.0000000000000000, 0.0000000000000000),
('12M0004893', 70, 0.0000000000000000, 1.2900000000000000),
('12M0004893', 70, 0.0000000000000000, 0.0000000000000000),
('12M0004893', 75, 0.0000000000000000, 3.8700000000000000),
('12M0004893', 75, 0.0000000000000000, 0.0000000000000000),
('12M0004893', 80, 0.0000000000000000, 0.5500000000000000),
('12M0003571', 3, 0.8900000000000000, 0.0000000000000000),
('12M0003571', 3, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 7, 1.0000000000000000, 0.0000000000000000),
('12M0003571', 10, 0.3000000000000000, 0.3000000000000000),
('12M0003571', 10, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 20, 0.0700000000000000, 0.1000000000000000),
('12M0003571', 20, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 30, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 40, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 50, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 60, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 60, 0.0000000000000000, 0.0000000000000000),
('12M0003571', 70, 0.0700000000000000, 0.1500000000000000),
('12M0003571', 70, 0.0000000000000000, 0.0000000000000000)
;
CREATE TABLE ProdRouteTran
([ProdID] varchar(10), [MaxOpCompleted] int, [Hours] numeric)
;
INSERT INTO ProdRouteTran
([ProdID], [MaxOpCompleted], [Hours])
VALUES
('12M0004893', 50, 1.7800000000000000),
('12M0003571', 70, 1.2660000000000000)
;
Run Code Online (Sandbox Code Playgroud)
预期产量:
ProdId OprNum
12M0004893 60
ProdId OprNum
12M0003571 70
Run Code Online (Sandbox Code Playgroud)
基于新数据和对问答的最后评论,这里是更新的查询和小提琴:http://sqlfiddle.com/#!6/ 87e2f/2
嘿,我发现了一个不起作用的例子... orderID'12M0003381'...我已经为你的小提琴添加了数据.我希望看到操作70,因为这是设置或处理时间的最后一次操作......谢谢!
select prodid, ISNULL(MAX(weighted_value),MIN(oprnum)) as value from
(
select
a.prodid,
a.oprnum,
ISNULL(LEAD(a.oprnum,1) OVER(Partition by a.prodID ORDER by a.oprnum asc),a.oprnum) *
MAX(case
when ISNULL([Hours], 0) >= (setupTime + ProcessTime) AND (SetupTime + ProcessTime ) > 0
then 1
else NULL
end) as weighted_value
from temp1 a LEFT JOIN temp4 b
ON a.OprNum = b.OPRNUM
AND a.ProdID = b.ProdId
group by a.prodid,a.oprnum
) t
group by prodid
Run Code Online (Sandbox Code Playgroud)
以下查询更改的说明:
对查询进行的唯一更改是处理使用以下语法的NULL值weighted_value
ISNULL(LEAD(a.oprnum,1) OVER(Partition by a.prodID ORDER by a.oprnum asc),a.oprnum)
Run Code Online (Sandbox Code Playgroud)
有问题的部分是内部查询,当没有group by子句运行时,会显示在用户添加的边界情况下发生的情况.
(请参阅此处的小提琴:http://sqlfiddle.com/#!6/ 87e2f/3)
如果没有null处理,我们有一个NULLafter group by子句导致如下结构
(请参阅此处的小提琴:http://sqlfiddle.com/#!6/ 87e2f/5)
正如你可以在分组牵头值见prodid : 12M0003381, oprnum:70如下,NULL而不是70(如分组70和NULL应该给予70).
如果LEAD在分组查询/表上计算,这是合理的,这实际上是在这里发生的事情.
在这种情况下,该LEAD函数不会返回最后一行分区的任何数据.这是边界情况,必须正确处理ISNULL.
我假设LEAD oprnum最后一行的值应该更正为oprnum当前行的值.
老答案如下:
所以我尝试了,我发布了小提琴链接 http://sqlfiddle.com/#!6/e965c/1
Run Code Online (Sandbox Code Playgroud)select prodid, ISNULL(MAX(weighted_value),MIN(oprnum)) as value from ( select a.prodid, a.oprnum, LEAD(a.oprnum,1) OVER(Partition by a.prodID ORDER by a.oprnum asc) * MAX(case when ISNULL([Hours], 0) >= (setupTime + ProcessTime) AND (SetupTime + ProcessTime ) > 0 then 1 else NULL end) as weighted_value from ProdRoute a LEFT JOIN COMPLETED_OP b ON a.OprNum = b.OPRNUM AND a.ProdID = b.ProdId group by a.prodid,a.oprnum ) t group by prodid
这不是我写过的最漂亮的东西,但它有效.我还用另外的数据对另一个小提琴进行了测试.
修改以满足新要求.
SELECT
*
FROM
(
SELECT
A.ProdID,
MIN(A.OprNum) AS 'OprNum'
FROM
#ProdRoute AS A
JOIN
(
SELECT
ProdID,
MAX(MaxOpCompleted) AS 'OprNum'
FROM
#ProdRouteTran
GROUP BY
ProdID
) AS B
ON A.ProdId = B.ProdId AND A.OprNum > B.OprNum
GROUP BY
A.ProdID
) AS [HoursA]
UNION ALL
SELECT
*
FROM
(
SELECT
DISTINCT
A.ProdID,
B.OprNum
FROM
#ProdRoute AS A
JOIN
(
SELECT
ProdID,
MAX(MaxOpCompleted) AS 'OprNum'
FROM
#ProdRouteTran
GROUP BY
ProdID
) AS B
ON A.ProdId = B.ProdId AND A.OprNum = B.OprNum
AND B.OprNum = (SELECT MAX(OprNum) FROM #ProdRoute WHERE ProdId = A.ProdId)
) AS [HoursB]
UNION ALL
SELECT
*
FROM
(
SELECT
ProdId,
MIN(OprNum) AS 'OprNum'
FROM
#ProdRoute
WHERE
ProdId NOT IN
(SELECT ProdId FROM #ProdRouteTran)
AND (SetupTime <> 0 OR ProcessTime <> 0)
GROUP BY
ProdId
) AS [NoHoursA]
UNION ALL
SELECT
*
FROM
(
SELECT
ProdId,
MIN(OprNum) AS 'OprNum'
FROM
#ProdRoute
WHERE
ProdId NOT IN
(SELECT ProdId FROM #ProdRouteTran)
GROUP BY
ProdId
HAVING
SUM(SetupTime) = 0 AND SUM(ProcessTime) = 0
) AS [NoHoursB]
Run Code Online (Sandbox Code Playgroud)
我不确定我理解你的问题,但这是我的尝试:
SELECT
pr.ProdId,
CASE
WHEN SUM(SetupTime) + SUM(ProcessTime) > 0 THEN MAX(x.OprNum)
ELSE MAX(pr.OprNum)
END
FROM ProdRoute pr
INNER JOIN (
SELECT ProdID, MAX(MaxOpCompleted) AS OprNum
FROM ProdRouteTran
GROUP BY ProdID
)prt
ON prt.ProdId = pr.ProdID
AND prt.OprNum = pr.OprNum
OUTER APPLY(
SELECT TOP 1 OprNum FROM ProdRoute
WHERE
ProdId = pr.ProdId
AND OprNum > pr.OprNum
ORDER BY OprNum
)x
GROUP BY pr.ProdId
ORDER BY pr.ProdId
Run Code Online (Sandbox Code Playgroud)
试试这个 -
-- display the next operation, if condition match
SELECT do_exists.ProdId, do_exists.OprNum
FROM ProdRoute pr
INNER JOIN ProdRouteTran prt
ON prt.ProdId = pr.ProdId
AND pr.OprNum = prt.MaxOpCompleted
AND (pr.SetupTime + pr.ProcessTime) > 0
OUTER APPLY (
SELECT TOP(1) pr.*
FROM ProdRoute pr
WHERE prt.ProdID = pr.ProdId
AND pr.OprNum > prt.MaxOpCompleted
ORDER BY pr.OprNum
) do_exists
UNION ALL
-- display the max operation, if matching data is not found in ProdRoute.
---- Matching Data not found - 1) There is entry in ProdRoute for particular ProdId but hours is not present
---- 2) There is no entry in ProdRoute for a particular ProdId
SELECT pr.ProdId, MAX(pr.OprNum) OprNum
FROM ProdRoute pr
LEFT JOIN (
SELECT pr.ProdId
FROM ProdRoute pr
INNER JOIN ProdRouteTran prt
ON prt.ProdId = pr.ProdId
AND pr.OprNum = prt.MaxOpCompleted
AND (pr.SetupTime + pr.ProcessTime) > 0
) pr_ex ON pr_ex.ProdId = pr.ProdId
WHERE pr_ex.ProdId IS NULL
GROUP BY pr.ProdId
Run Code Online (Sandbox Code Playgroud)
我用这个SQL Fiddle得到了正确的结果.
但是我不确定我是否完全理解这个nothing >0案子.所有案例的更多数据可能是有用的.
; With data as (
Select r.ProdId
, opr = case when h > 0 then isnull(min(p.OprNum), r.OprNum) else max(p.OprNum) end
From (
Select pr.ProdId, pr.OprNum, h = max(pr.SetupTime + pr.ProcessTime)
From ProdRoute as pr
Inner Join ProdRouteTran as prt on pr.ProdId = prt.ProdID and pr.OprNum = prt.MaxOpCompleted
Group By pr.ProdId, pr.OprNum
) as r
left join ProdRoute as p on p.ProdId = r.ProdId and p.OprNum > r.OprNum
Group By r.ProdId, r.OprNum, r.h
)
Select * From data
Run Code Online (Sandbox Code Playgroud)
我不完全确定我是否明白你要做什么,但这可能是等同的吗?
SELECT
t.ProdId,
CASE WHEN r.OprNum IS NULL THEN t.MaxOpCompleted ELSE r.OprNum END AS OprNum
FROM
ProdRouteTran t
LEFT JOIN
ProdRoute r
ON
r.ProdId = t.ProdId AND r.SetupTime + r.ProcessTime > 0 AND
r.OprNum > t.MaxOpCompleted AND NOT EXISTS(
SELECT * FROM ProdRoute p WHERE p.ProdId = t.ProdId AND
p.OprNum > t.MaxOpCompleted AND p.OprNum < r.OprNum)
Run Code Online (Sandbox Code Playgroud)