带 MAX 函数的内连接 - SQL SERVER-

Posted

技术标签:

【中文标题】带 MAX 函数的内连接 - SQL SERVER-【英文标题】:Inner Join With MAX function - SQLSERVER- 【发布时间】:2015-03-19 02:40:46 【问题描述】:

我一直在寻找解决问题的方法,但相信我做错了什么。

我需要在表格中选择一行,并且该行有一个名为“SEQ”的列,其值从 0 到 200 (10-10)。结果,具有最大 SEQ 字段但小于第一个选择的行。

示例:

+----------------------------+
| cod   cod_os   task    seq |
+----------------------------+
| 1     9000     wash    10  |
| 2     9000     dry     20  |
| 3     9000     polish  40  |
| 4     9003     ****    10  |
| 5     9000     park    80  |
| 6     9003     ****    20  |
| 7     9020     ****    10  |
| 8     9007     ****    10  |
| 9     9010     ****    10  |
| 10    9009     ****    10  |
| 11    9003     ****    30  |
| 12    9001     ****    10  |
| 13    9002     ****    10  |
| 14    9003     ****    40  |
| 15    9001     ****    20  |
+----------------------------+

预期结果:

Obs:当任务不属于他们的“操作系统”时,结果应该是任务本身。例如:'wash' 是 'wach' 的时间越早。

+------------------------------------+
| cod   cod_os   task    seq    prev |
+------------------------------------+
| 1     9000     wash    10       1  |
| 2     9000     dry     20       1  |
| 3     9000     polish  40       2  |
| 4     9003     ****    10       4  |
| 5     9000     park    80       3  |
| 6     9003     ****    20       4  |
| 7     9020     ****    10       7  |
| 8     9007     ****    10       8  |
| 9     9010     ****    10       9  |
| 10    9009     ****    10       10 |
| 11    9003     ****    30       6  |
| 12    9001     ****    10       12 |
| 13    9002     ****    10       13 |
| 14    9003     ****    40       11 |
| 15    9001     ****    20       12 |
+------------------------------------+

获取我的代码(SQL SERVER 2008):

    select
CAST(T0.COD_OS AS VARCHAR) +'/'+ RIGHT(('000' + CAST(T0.COD_OS_AUX AS VARCHAR)),3) 'OS_COMPLETO',
    T1.TIPO 'TIPOSERVICO',
    T2.NOME 'MAQUINA',
    T3.SUBTITULO 'SUB',
    T4.CLIENTE 'CLIENTE',
    T3.QTDE_PECAS 'QTD',
    t0.CODIGO 'COD',
    t0.SEQ 'SEQ',
    t0.OBS 'OBS',
    t0.DT_INCIO_PREVISTO 'INICIO',
    t0.DT_TERMINO_PREVISTO 'FIM',
    t0.TOTAL_HRS_TIME 'TOTAL',
    T4.CANCELADO,
    T4.CONCLUIDO,
    T5.SEQ 'ANTERIOR',
    (CASE WHEN T1.TIPO <> T6.TIPO THEN T6.TIPO ELSE 'REQ. MATERIAIS' END) 'ANTERIOR'

from [ProjectOne].[dbo].[TPRO_PRO] T0
    INNER JOIN [ProjectOne].[dbo].[TTP_MAQU] T1 ON T0.COD_TP_SERVICO=T1.CODIGO
    INNER JOIN [ProjectOne].[dbo].[TMAQUINA] T2 ON T0.COD_MAQUINA=T2.CODIGO
    INNER JOIN [ProjectOne].[dbo].[TOS_AUX] T3 ON T0.COD_OS=T3.COD_OS AND T0.COD_OS_AUX=T3.CODIGO
    INNER JOIN [ProjectOne].[dbo].[TPRO_PRO] T5 ON T5.COD_OS = T0.COD_OS AND T5.COD_OS_AUX = T0.COD_OS_AUX AND T0.SEQ > t5.SEQ
    INNER JOIN [ProjectOne].[dbo].[TTP_MAQU] T6 ON T5.COD_TP_SERVICO=T6.CODIGO     
    INNER JOIN 
    (
        SELECT T0.CODIGO,T0.CANCELADO,T0.CONCLUIDO, T1.NOME AS CLIENTE
        FROM [ProjectOne].[dbo].[TOS] T0 INNER JOIN [ProjectOne].[dbo].[TCLIENTE] T1 ON T0.COD_CLIENTE=T1.CODIGO
    ) T4 ON T4.CODIGO=T0.COD_OS AND T4.CANCELADO=0 AND T4.CONCLUIDO=0 and T0.FINALIZADO=0 and T3.COD_STAUS not in (3,4)
WHERE T0.DT_INCIO_PREVISTO <> '' 
ORDER BY T1.TIPO, t0.DT_TERMINO_PREVISTO, t0.COD_OS, T0.COD_OS_AUX

【问题讨论】:

您要求该行包含 SEQ 的最大值,但也小于您从第一个查询中获得的值。这似乎是一个矛盾,因为它不能同时满足这两个条件。您的意思是它应该返回 SEQ 值是小于第一个 SEQ 的最大值的行吗?此外,您希望它在可能从第二个查询返回多个元组的情况下如何反应? 我有一个 'jobs' 序列,当我选择一个 'job' 时,它们是由这个 ' SEQ ' 字段组织的,我知道以前的 'job' 。问题是,上一个 50 的作业并不总是 40,例如,如果一个已被删除,它可能是 30 或 20。 当 'job' 是第一个,因此具有最低的 ' SEQ' 想返回这个相同的任务重复,或者没有。 我的意思是,在您的示例中,Leandro 和 Julio 都具有 SEQ 20,还有 Jonas 和 Maria。如果它们应该是第二个查询的返回,那么由于返回的可能值有两个或多个,应该如何处理结果。 使用上面的代码,我的结果是几个重复的“工作”,显示所有以前的“工作”。例如,当我有 'jobs' 40 时,他向我展示 40 与 30 是最后一个,到 40 与 20 是前面和 40 与 10 是前一个 【参考方案1】:

不知道是不是你要找的, 但是鉴于您示例中的表格, 如果您在同一个 code_os 上将其与自身连接并在 SEQ 值上添加条件(因此它会低于所选行),选择顶行不会给您所需的内容吗?

CREATE TABLE [dbo].[TestSEQ](
    [cod] [int] NULL,
    [cod_os] [int] NULL,
    [task] [varchar](50) NULL,
    [seq] [int] NULL
) ON [PRIMARY]


INSERT INTO [dbo].[TestSEQ]
           ([cod]
           ,[cod_os]
           ,[task]
           ,[seq])
     VALUES
           (1,9000,'wash',10),
           (2,9000,'dry',20),
           (3,9000,'polish',40),
           (4,9003,'****',10),
           (5,9000,'park',80),
           (6,9003,'****',20),
           (7,9020,'****',10),
           (8,9007,'****',10),
           (9,9010,'****',10),
           (10,9009,'****',10),
           (11,9003,'****',30),
           (12,9001,'****',10),
           (13,9002,'****',10),
           (14,9003,'****',40),
           (15,9001,'****',20)           
GO

declare @task varchar(50) = 'park'

SELECT  top 1 b.*
FROM    [TestSEQ] a 
    inner join [TestSEQ] b 
        on a.cod_os = b.cod_os
where 1=1
and a.cod_os = 9000
and a.task = @task
and b.seq < a.seq
order by b.seq desc

对于所有行:

SELECT  *
FROM    
(
    SELECT  a.* , max(b.seq) NextSEQAfterMax
    FROM    [TestSEQ] a 
        inner join [TestSEQ] b 
            on a.cod_os = b.cod_os
    where 1=1
    and b.seq < a.seq
    group by a.cod , a.cod_os , a.task , a.seq
) a
    inner join TestSEQ b
        on a.cod_os = b.cod_os
        and a.NextSEQAfterMax = b.seq

【讨论】:

您的代码可以成为解决我的问题的开始。但他的问题是我不是只选择一条线,我必须选择所有处于某种状态的,以及他们以前的任务。使用您的代码,我只得到一个结果行。 检查您调整代码的方式,您的示例中没有 50,因此我无法验证您的评论,但请注意仅当第二个表中的 seq 较低时,join 语句才会连接行,以排除平等的情况。祝你好运,希望你能成功。 我设法使用您的解决方案解决了我的问题。感谢您的帮助。 很高兴为您提供帮助,如果对您有帮助,请标记答案,晚安,伙计。

以上是关于带 MAX 函数的内连接 - SQL SERVER-的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 创建带返回值的存储过程

我正在寻找一对将返回日期列表的 MAX 或 MIN 的 SQL 函数 (MS SQL Server)

sql server 函数

为啥我们在 SQL Server 中透视文本列时使用 Max 函数?

Python学习笔记 - 最牛逼的内建函数max和min

怎么查看sql server 版本