Sql 如何过滤重复的行并对数据进行排序,而不包括SELECT上的ORDER BY字段?

Sql 如何过滤重复的行并对数据进行排序,而不包括SELECT上的ORDER BY字段?,sql,sql-server,Sql,Sql Server,我在SQL Server上声明了以下存储过程: ALTER PROCEDURE [dbo].[ContratoMarcoGP_FuerzaTrabajo] @IdContratoMarco INT = NULL, @Desde DATETIME, @Hasta DATETIME, @IdSede INT, @IdIdioma INT, @IdProveedor INT AS BEG

我在SQL Server上声明了以下存储过程:

ALTER PROCEDURE [dbo].[ContratoMarcoGP_FuerzaTrabajo]
@IdContratoMarco    INT = NULL,
@Desde              DATETIME,
@Hasta              DATETIME,
@IdSede             INT,
@IdIdioma           INT,
@IdProveedor        INT
AS
BEGIN

SELECT 
            CAST(PD.[IdPeriodoDetalle] AS VARCHAR) + '-' + CAST(E.[IdEspecialidad] AS VARCHAR) AS [IdUnico], -- generado para el storetable
            PD.[IdPeriodoDetalle],
            M.[Descripcion] + ' - ' + CAST(PD.[Anio] AS CHAR(4)) AS [PeriodoDetalle], 
            E.[IdEspecialidad], 
            E.[Descripcion] AS [Especialidad], 
            CAST(
                (CASE 
                    WHEN CMH.[Horas] IS NULL THEN 0
                    ELSE CMH.[Horas]
                END) 
            AS INT)AS [Horas]
        FROM 
            [PeriodoDetalle] PD 
            INNER JOIN ProveedorPersona PP ON PP.IdProveedor = @IdProveedor
            INNER JOIN [Especialidad] E ON E.IdEspecialidad = PP.IdEspecialidad
            LEFT JOIN [ContratoMarcoHoras] CMH ON E.[IdEspecialidad] = CMH.[IdEspecialidad] AND PD.[IdPeriodoDetalle] = CMH.[IdPeriodoDetalle] AND CMH.[IdContratoMarco] = @IdContratoMarco -- traigo las horas cargadas sólo para el contrato indicado.
            INNER JOIN [Mes] M ON PD.[Mes] = M.[IdMes] AND M.[IdIdioma] = @IdIdioma
        WHERE 
        (   
            [FechaDesdeGP] BETWEEN @Desde AND @Hasta
        OR  
            [FechaHastaGP] BETWEEN @Desde AND @Hasta
        OR
            (
                @Desde BETWEEN [FechaDesdeGP] AND [FechaHastaGP]
            OR
                @Hasta BETWEEN [FechaDesdeGP] AND [FechaHastaGP]
            )
        )
        AND
            PD.[IdSede] = @IdSede
        AND
            E.[IdIdioma] = @IdIdioma
        AND 
            PP.IdProveedor = @IdProveedor   
        ORDER BY 
            PD.[Anio], PD.[Mes]
END
问题是,当我用几个参数调用这个过程时,它会返回一些重复的行,因此我想使用DISTINCT keywork,但它告诉我需要在SELECT中包含ORDER BY中指定的字段,我不希望这样做。我的意思是,我只需要包括我在SELECT子句中指定的字段,因为它在C数据表中返回这些数据。 如何按此字段对数据进行排序并过滤重复的行,而不在SELECT中包含新字段?是否可能在两个步骤中使用子查询来筛选所需字段?

使用group by,然后在order by中包含聚合函数,而不是使用distinct。以下是基于您的查询的模板:

select CAST(PD.[IdPeriodoDetalle] AS VARCHAR(255)) + '-' + CAST(E.[IdEspecialidad] AS VARCHAR(255)) AS [IdUnico],
       . . .
from [PeriodoDetalle] PD 
     . . .
where . . .
group by <all the columns in the select>
order by max(PD.[Anio]), max(PD.[Mes]);

注意,我为varchar添加了长度参数。在SQL Server中,应始终包含字段的长度。默认值因上下文而异,依赖默认值可能会产生难以发现的bug。

我不太理解这个问题,但至少有一部分:

但它告诉我,我需要在SELECT中包含orderby中指定的字段,我不希望这样做

也许是一张临时桌子

例如:如果需要此选项:

select distinct date,value from dbo.TAB_A2
order by id
这将产生一个错误。相反:

create table #tab_a3(id int, date datetime,value int)

insert into #tab_A3
    select distinct id, date,value 
    from dbo.TAB_A2
    order by id

select date,value from #tab_A3

删除ORDER BY并在DataTable的C中执行?以下是两个简单的蛮力答案。。。1去掉order by并在c代码中进行排序。2添加列,然后将整个内容包装在子选择中。但是,你最好还是按照戈登的答案去做谢谢Tanner,这可能是另一个好方法。我想这样做,但我更喜欢在数据库中有完整的逻辑。那些列当前不在SELECT中,但以ORDER BY的形式出现-对于SELECT子句中所有列都匹配的行,它们可能包含多个不同的值。DISTINCT将把这些列减少为一行-服务器如何知道这些列使用什么值?Gordon的答案解决了我的问题。在这一行中,我的意思是,如果使用DISTINCT关键字,则需要在SELECT上写入在ORDERBY子句上设置的任何字段。无论如何谢谢你!也许我可以帮助其他人:当Gordon写他的答案时,我正忙着测试这个问题,对于你写的那行,应该有F5'ed:P,这解决了这个问题,因为在我的例子中,我不会得到最终结果。不管怎样,很高兴看到你得到了答案:非常感谢戈登!!它以一种非常有效的方式解决了我的问题。这是一个非常好的回答。