获取具有MIN / MAX值的行的其他字段值

时间:2012-12-20 19:58:52

标签: sql-server tsql max aggregate min

以下是我的数据示例以及我希望看到的内容:

JOB    OPSEQ    OPCOMPLETE   OPCODE

100     1        yes          pull  
100     2        yes          weld  
100     3        no           grind    
100     4        no           machine  
100     5        no           asmbl  

所以我想选择min(opseq),其中opcomplete = no和max(opseq),其中opcomplete = yes,以及min和max opseq的操作码。在这个例子中将是:
分钟(opseq):3
min op的操作码:grind
max(opseq):2 max op:weld

的操作码

我正在寻找这个的原因是获得最不完整的opseq的操作码 我让min和max opseq工作得很好。这就是我所拥有的:

(SELECT   company, jobnum, MAX(oprseq) AS maxclosed, opcomplete
 FROM     joboper AS joboper_2
 WHERE    (company = 'lot') AND (opcomplete = '1')
 GROUP BY company, jobnum, opcomplete) AS t_joboper1 ON joboper.company = t_joboper1.company AND joboper.jobnum = t_joboper1.jobnum INNER JOIN
(SELECT   company, jobnum, MIN(oprseq) AS minopen, opcomplete
 FROM     joboper AS joboper_1
 WHERE    (company = 'lot') AND (opcomplete = '0')
 GROUP BY company, jobnum, opcomplete) AS t_joboper2 ON joboper.company = t_joboper2.company AND joboper.jobnum = t_joboper2.jobnum  

因此,当我尝试添加我的操作码时,它不起作用,我开始获得各种重复值。这就是我写的:

(SELECT   company, jobnum, MAX(oprseq) AS maxclosed, opcomplete, opcode as maxopcode
 FROM     joboper AS joboper_2
 WHERE    (company = 'lot') AND (opcomplete = '1')
 GROUP BY company, jobnum, opcomplete, opcode) AS t_joboper1 ON joboper.company = t_joboper1.company AND joboper.jobnum = t_joboper1.jobnum INNER JOIN
(SELECT   company, jobnum, MIN(oprseq) AS minopen, opcomplete, opcode as minopcode
 FROM     joboper AS joboper_1
 WHERE    (company = 'lot') AND (opcomplete = '0')
 GROUP BY company, jobnum, opcomplete, opcode) AS t_joboper2 ON joboper.company = t_joboper2.company AND joboper.jobnum = t_joboper2.jobnum  

这是我现在的整个代码(使用操作码拉入所有重复的值:

SELECT     jobhead.company, jobhead.jobnum, jobhead.partnum, 
           jobhead.partdescription, jobhead.startdate, 
           jobhead.reqduedate, jobhead.prodqty, jobhead.qtycompleted,
           joboper.oprseq, joboper.opcode, joboper.opcomplete, 
           joboper.qtycompleted AS joboperqtycomplete, 
           resourcegroup.description AS rgroupdescription,
           dmrhead.dmrnum, poheader.ponum, vendor.name AS vendorname,
           t_joboper2.minopen AS minopen, t_joboper2.minopcode AS minopcode,
           t_joboper1.maxclosed AS maxclosed, t_joboper1.maxopcode AS maxopcode
FROM       jobhead LEFT OUTER JOIN
           joboper INNER JOIN
           (SELECT   company, jobnum, MAX(oprseq) AS maxclosed, 
                     opcomplete, opcode as maxopcode
            FROM     joboper AS joboper_2
            WHERE    (company = 'lot') AND (opcomplete = '1')
            GROUP BY company, jobnum, opcomplete, opcode) AS t_joboper1 
              ON     joboper.company = t_joboper1.company 
            AND      joboper.jobnum = t_joboper1.jobnum INNER JOIN
           (SELECT   company, jobnum, MIN(oprseq) AS minopen, opcomplete, 
                     opcode as minopcode
            FROM     joboper AS joboper_1
            WHERE    (company = 'lot') AND (opcomplete = '0')
            GROUP BY company, jobnum, opcomplete, opcode) AS t_joboper2 
              ON     joboper.company = t_joboper2.company
            AND      joboper.jobnum = t_joboper2.jobnum 
              ON     jobhead.company = joboper.company
            AND      jobhead.jobnum = joboper.jobnum LEFT OUTER JOIN
                     resourcegroup ON joboper.company = resourcegroup.company
            AND      joboper.opcode = resourcegroup.opcode LEFT OUTER JOIN
                     dmrhead ON joboper.company = dmrhead.company
            AND      joboper.jobnum = dmrhead.jobnum
            AND      joboper.assemblyseq = dmrhead.assemblyseq 
            AND      joboper.oprseq = dmrhead.oprseq LEFT OUTER JOIN
                     porel ON joboper.company = porel.company
            AND      joboper.jobnum = porel.jobnum
            AND      joboper.assemblyseq = porel.assemblyseq
            AND      joboper.oprseq = porel.jobseq LEFT OUTER JOIN
                     podetail ON porel.company = podetail.company
            AND      porel.ponum = podetail.ponum 
            AND      porel.poline = podetail.poline LEFT OUTER JOIN
                     poheader ON podetail.company = poheader.company 
            AND      podetail.ponum = poheader.ponum LEFT OUTER JOIN
                     vendor ON poheader.company = vendor.company
            AND      poheader.vendornum = vendor.vendornum  
WHERE     (jobhead.jobreleased = 1)
 AND      (jobhead.jobcomplete = 0) 
 AND      (jobhead.company = 'lot') 
 AND      (jobhead.plant = '001')  

我希望这一切都有意义我想在这里做些什么。如果不是很明显,这是我第一次在这里问一个问题。我提前感谢所有的帮助!!!

新 - 12-21-12

谢谢你的帮助!我尝试了你的两个建议,但无法得到任何一个得到我想要的确切结果。但是每个答案都帮助我了解了最终需要的东西。由于这是我的第一个问题,我不知道我应该做些什么来标记哪个答案作为解决方案?就像我说的那样,这两个答案都帮助了我很多,我认为我无法得到我想要的结果的原因是我的错。在进行了更多的工作之后,我意识到即使我在我的问题中努力清楚,但是当我回去时,我看到我可以更好地措辞。再次,我非常感谢所有的帮助,我期待将来提出更好的问题! 顺便说一下,这是最终有效的代码。

 SELECT     jobhead.company, jobhead.jobnum, jobhead.partnum, jobhead.partdescription, jobhead.startdate, jobhead.reqduedate, jobhead.prodqty, jobhead.qtycompleted, 
                  joboper.oprseq, joboper.opcode, joboper.opcomplete, joboper.qtycompleted AS joboperqtycomplete, resourcegroup.description AS rgroupdescription, 
                  dmrhead.dmrnum, poheader.ponum, vendor.name AS vendorname, t_joboper2.minopen, t_joboper1.maxclosed, t_joboper3.opcode AS minopcode
FROM         jobhead LEFT OUTER JOIN
                  joboper INNER JOIN
                      (SELECT     company, jobnum, MAX(oprseq) AS maxclosed, opcomplete
                        FROM          joboper AS joboper_1
                        WHERE      (company = 'lot') AND (opcomplete = '1')
                        GROUP BY company, jobnum, opcomplete) AS t_joboper1 ON joboper.company = t_joboper1.company AND joboper.jobnum = t_joboper1.jobnum INNER JOIN
                      (SELECT     company, jobnum, MIN(oprseq) AS minopen, opcomplete
                        FROM          joboper AS joboper_2
                        WHERE      (company = 'lot') AND (opcomplete = '0')
                        GROUP BY company, jobnum, opcomplete) AS t_joboper2 ON joboper.company = t_joboper2.company AND 
                  joboper.jobnum = t_joboper2.jobnum INNER JOIN
                      (SELECT     company, jobnum, oprseq, opcomplete, opcode
                        FROM          joboper AS joboper_3
                        WHERE      (company = 'lot') AND (opcomplete = '0'))
                         AS t_joboper3 ON t_joboper2.company = t_joboper3.company AND t_joboper2.jobnum = t_joboper3.jobnum AND 
                  t_joboper2.minopen = t_joboper3.oprseq ON jobhead.company = joboper.company AND jobhead.jobnum = joboper.jobnum LEFT OUTER JOIN
                  resourcegroup ON joboper.company = resourcegroup.company AND joboper.opcode = resourcegroup.opcode LEFT OUTER JOIN
                  dmrhead ON joboper.company = dmrhead.company AND joboper.jobnum = dmrhead.jobnum AND joboper.assemblyseq = dmrhead.assemblyseq AND 
                  joboper.oprseq = dmrhead.oprseq LEFT OUTER JOIN
                  porel ON joboper.company = porel.company AND joboper.jobnum = porel.jobnum AND joboper.assemblyseq = porel.assemblyseq AND 
                  joboper.oprseq = porel.jobseq LEFT OUTER JOIN
                  podetail ON porel.company = podetail.company AND porel.ponum = podetail.ponum AND porel.poline = podetail.poline LEFT OUTER JOIN
                  poheader ON podetail.company = poheader.company AND podetail.ponum = poheader.ponum LEFT OUTER JOIN
                  vendor ON poheader.company = vendor.company AND poheader.vendornum = vendor.vendornum
WHERE     (jobhead.jobreleased = 1) AND (jobhead.jobcomplete = 0) AND (jobhead.company = 'lot') AND (jobhead.plant = '001')            

3 个答案:

答案 0 :(得分:5)

这是一种方法:

select JOB,
       min(case when OPCOMPLETE = 'no' then OPSEQ end) as MIN_NO_OPSEQ,
       min(case when OPCOMPLETE = 'no' then OPCODE end) as MIN_NO_OPCODE,
       min(case when OPCOMPLETE = 'yes' then OPSEQ end) as MAX_YES_OPSEQ,
       min(case when OPCOMPLETE = 'yes' then OPCODE end) as MAX_YES_OPCODE
  from ( select JOB,
                OPSEQ,
                OPCOMPLETE,
                OPCODE,
                rank() over (partition by JOB, OPCOMPLETE order by OPSEQ asc) as R_NO,
                rank() over (partition by JOB, OPCOMPLETE order by OPSEQ desc) as R_YES
           from TABLE_NAME
       )
 where OPCOMPLETE = 'no' and R_NO = 1    -- row with min(OPSEQ) where OPCOMPLETE = 'no'
    or OPCOMPLETE = 'yes' and R_YES = 1  -- row with max(OPSEQ) where OPCOMPLETE = 'yes'
 group
    by JOB
;

注意:

  • 未经测试。
  • 在第2-5行中,每个min都可以更改为max而不起作用,因为只有一行符合所有必要条件。由于minmax(或group by}是必需的:我们通过选择非空值将两行合并为一个。
  • 有关rank()的信息,请参阅its documentation on MSDN

答案 1 :(得分:3)

我认为这比你制作它容易得多,只要OPSEQ是一个独特的价值:

select
    opseq, opcode
from
    joboper
where
    opseq in (select min(opseq) from joboper where opcomplete = 'no')
    or
    opseq in (select max(opseq) from joboper where opcomplete = 'yes')

答案 2 :(得分:1)

假设您使用的是SQL Server 2005或更高版本,您还可以考虑使用CROSS APPLY,如下所示:

SELECT
  j.JOB,
  y.OPSEQ  AS LastCompleteOPSEQ,
  y.OPCODE AS LastCompleteOPCODE,
  n.OPSEQ  AS FirstIncompleteOPSEQ,
  n.OPCODE AS FirstIncompleteOPCODE
FROM (SELECT DISTINCT JOB FROM joboper) j
CROSS APPLY (
  SELECT TOP 1 OPSEQ, OPCODE
  FROM joboper
  WHERE JOB = j.JOB AND OPCOMPLETE = 'yes'
  ORDER BY OPSEQ DESC
) y
CROSS APPLY (
  SELECT TOP 1 OPSEQ, OPCODE
  FROM joboper
  WHERE JOB = j.JOB AND OPCOMPLETE = 'no'
  ORDER BY OPSEQ ASC
) n
;

您可以查询at SQL Fiddle