sql根据条件第2部分选择min或max

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)

Dhr*_*shi 8

基于新数据和对问答的最后评论,这里是更新的查询和小提琴: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)

以下查询更改的说明:

对查询进行的唯一更改是处理使用以下语法的NULLweighted_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(如分组70NULL应该给予70).

如果LEAD在分组查询/表上计算,这是合理的,这实际上是在这里发生的事情.

在这种情况下,该LEAD函数不会返回最后一行分区的任何数据.这是边界情况,必须正确处理ISNULL.

我假设LEAD oprnum最后一行的值应该更正为oprnum当前行的值.

老答案如下:

所以我尝试了,我发布了小提琴链接 http://sqlfiddle.com/#!6/e965c/1

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
Run Code Online (Sandbox Code Playgroud)


Chr*_*ert 6

这不是我写过的最漂亮的东西,但它有效.我还用另外的数据对另一个小提琴进行了测试.

修改以满足新要求.

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)


Fel*_*tan 6

我不确定我理解你的问题,但这是我的尝试:

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)


Age*_*SQL 6

试试这个 -

-- 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)


Jul*_*eur 6

我用这个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)


mar*_*aca 5

我不完全确定我是否明白你要做什么,但这可能是等同的吗?

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)