2

我想根据表格中的日期范围选择数据,并获取该日期范围之前的最新值。

我怎样才能使它更有效率?

该表定义为:

Name       varchar(100)   Checked
DataType   varchar(100)   Checked
Time       datetime       Checked
Value      int            Checked

该表包含以下数据:

Name    DataType  Time                      Value
Name1   Type1     2010-09-29 17:29:00.000   999
Name2   Type2     2013-11-02 06:51:00.000   0

我创建了以下查询,虽然有点冗长,但它确实返回了正确的结果。但是,我想知道这是否可以使用更好的 T-SQL 来实现?

我将在我的应用程序中将代码编写为内联 SQL

DECLARE @effectiveFrom DATETIME
SET @effectiveFrom = '2010-09-29 17:30:00'
DECLARE @effectiveTo DATETIME
SET @effectiveTo = '2010-09-29 17:49:00'
DECLARE @bmunit varchar(100)
DECLARE @datatype varchar(100)

--Select * from [Table] 
--where  (Time >= '2010-09-29 17:30:00' and Time < '2010-09-29     17:49:00') 

--union Select top 1 * from [Table]
-- where  Time < '2010-09-29 17:30:00' order by Time desc
SELECT P1.[Name]
      ,P1.[DataType]
      ,P1.[Time]
      ,P1.[Value]
      ,P1.Que
FROM
(
  SELECT  [Name]
      ,[DataType]
      ,[Time]
      ,[Value]
      , 'between' AS [Que]
  FROM [Table]
  WHERE  Time >= @effectiveFrom AND  EffectiveTime < @effectiveTo
) P1   
UNION SELECT P2.[Name]
      ,P2.[DataType]
      ,P2.[Time]
      ,P2.[Value]
      , 'before' AS [Que]
FROM
(
  SELECT TOP 1 [Name]
      ,[DataType]
      ,Time]
      ,[Value]
  FROM [Table] P1
  WHERE  Time < @effectiveFrom

) P2 --ON P1.[Name] = P2.[Name] AND P1.[DataType] = P2.[DataType]
WHERE Name = 'MyName' --AND P1.Time >= @effectiveFrom AND P1.Time < @effectiveTo
ORDER BY 2,3  
4

1 回答 1

2

您应该能够将其缩减为以下内容:

SELECT P1.[Name]
      ,P1.[DataType]
      ,P1.[Time]
      ,P1.[Value]
      ,'between' AS Que
FROM [Table] P1
WHERE Time >= @effectiveFrom AND Time < @effectiveTo
      AND Name = 'MyName'
UNION ALL
SELECT * FROM (
    SELECT TOP 1 P2.[Name]
          ,P2.[DataType]
          ,P2.[Time]
          ,P2.[Value]
          ,'before' AS [Que]
    FROM [Table] P2
    WHERE Time < @effectiveFrom
          AND Name = 'MyName'
    ORDER BY 3
) A

如果您不喜欢重复名称检查,则选择会变得更大:

SELECT * FROM (
    SELECT P1.[Name]
          ,P1.[DataType]
          ,P1.[Time]
          ,P1.[Value]
          ,'between' AS Que
    FROM [Table] P1
    WHERE Time >= @effectiveFrom AND Time < @effectiveTo
    UNION ALL
    SELECT * FROM (
        SELECT TOP 1 P2.[Name]
            ,P2.[DataType]
            ,P2.[Time]
            ,P2.[Value]
            ,'before' AS [Que]
        FROM [Table] P2
        WHERE Time < @effectiveFrom
        ORDER BY 3
    ) A
) B
WHERE Name = 'MyName'

如果你想让它更短,你可以试试这个,但我认为它的可读性较差:

SELECT P1.[Name]
      ,P1.[DataType]
      ,P1.[Time]
      ,P1.[Value]
      ,(CASE WHEN Time >= @effectiveFrom THEN 'between' ELSE 'before' END) AS Que
FROM [Table] P1
WHERE Name = 'MyName'
      AND 
      (
          (Time >= @effectiveFrom AND Time < @effectiveTo)
          OR (Time < @effectiveFrom AND NOT EXISTS (SELECT * 
                                                FROM [Table] P2 
                                                WHERE Time < @effectiveFrom
                                                    AND P2.Time > P1.Time)
          )
      )

是不是更短了?

于 2013-11-11T13:49:57.570 回答