在SQL中应用转换

时间:2015-02-06 08:53:39

标签: sql

道歉,如果这很难理解,我在一家调查公司工作,而且对SQL来说相对较新。

我有以下两个表:

targetReadings

id Epoch PointNumber Easting Northing

targetShift

ID Epoch PointNumber ShiftEasting ShiftNorthing

我们有数据自动进入 targetReadings 。然后我们在图表上绘制这些图表以在我们的网站上查看有时我们需要对我们的数据进行轮班。我需要一个将遍历数据并应用正确的移位值的查询。例如,如果我有一个名为R101的点,其坐标为East 100, North 500。这可能会受到打击,最新的阅读可能会East 101, North 501。然后我会在 targetShift 中输入一个条目:

 2015-01-01, R101, -1, -1 

然后一周之后,它可能会再次被击倒并给我East 105, North 105的读数。然后我会在 targetShift 中添加另一个条目:

2015-01-08, R101, -4, -4

我需要一个查询来运行 targetReadings 中的数据,并根据 targetShift 中的数据应用正确的班次。

我当前的查询是

SELECT 
    CASE WHEN a.Epoch > r.Epoch 
    THEN a.Easting + r.ShiftEasting
    END as ShiftEast
    , a.PointNumber
    , a.Epoch
    , r.Epoch
FROM
    TargetReadings a
    inner join targetShift r on r.PointNumber = a.PointNumber

这有效,但它会为 targetShift 中的每个条目带来一个结果,因为这是一个大型项目,每个点可能会有很多变化。我只想在 targetReadings 中的每个条目获得1个结果。

感谢您的帮助。

以下是一些示例数据,我有两个表的数据,下面是我想从查询中得到的结果:

TargetShift

PointNumber Epoch               ShiftEasting    ShiftNorthing
CB501       01/01/2014 00:00    0               0
CB501       01/01/2015 00:00    100000          100000
CB501       02/01/2015 00:00    200000          200000

TargetReadings

PointNumber Epoch               Easting     Northing
CB501       31/12/2014 00:01    528196.679  178392.171
CB501       31/12/2014 01:01    528196.679  178392.170
CB501       01/01/2015 00:01    528196.675  178392.165
CB501       01/01/2015 01:01    528196.676  178392.166
CB501       02/01/2015 00:01    528196.679  178392.167
CB501       02/01/2015 05:01    528196.679  178392.167

预期查询结果

PointNumber Epoch               ShiftEasting    ShiftNorthing
CB501       31/12/2014 00:01    528196.679      178392.171
CB501       31/12/2014 01:01    528196.679      178392.170
CB501       01/01/2015 00:01    628196.675      278392.165
CB501       01/01/2015 01:01    628196.676      278392.166
CB501       02/01/2015 00:01    728196.679      378392.167
CB501       02/01/2015 05:01    728196.679      378392.167

4 个答案:

答案 0 :(得分:0)

在这种情况下使用CROSS APLLY

SELECT
CASE WHEN a.Epoch > r.Epoch
THEN a.Easting + r.ShiftEasting
END as ShiftEast, a.PointNumber, a.Epoch, r.Epoch
FROM TargetReadings a
cross apply( select top 1 ts.* from targetShift ts where ts.PointNumber = a.PointNumber order by ID desc) r

答案 1 :(得分:0)

尝试这样,它只是表明,

 SELECT CASE 
        WHEN a.Epoch > r.Epoch
            THEN a.Easting + r.ShiftEasting
        END AS ShiftEast
    ,a.PointNumber
    ,a.Epoch
    ,r.Epoch
FROM TargetReadings a
INNER JOIN (
    SELECT *
        ,ROW_NUMBER() OVER (
            PARTITION BY PointNumber ORDER BY [datecolumn] DESC
            ) rn
    FROM targetshift
    ) r ON r.PointNumber = a.PointNumber
WHERE r.rn = 1

答案 2 :(得分:0)

在检查了示例数据和您在评论中的说明之后,您似乎并不想总结所有轮班,但您只想添加最近的轮班,如果有的话。在这种情况下,OUTER APPLY似乎是最佳选择。

示例数据:

DECLARE @TargetShift TABLE (PointNumber char(5), Epoch datetime, ShiftEasting float, ShiftNorthing float);
INSERT INTO @TargetShift (PointNumber, Epoch, ShiftEasting, ShiftNorthing) VALUES 
('CB501', '2014-01-01T00:00:00', 0     , 0     ),
('CB501', '2015-01-01T00:00:00', 100000, 100000),
('CB501', '2015-01-02T00:00:00', 200000, 200000);

DECLARE @TargetReadings TABLE (PointNumber char(5), Epoch datetime, Easting float, Northing float);
INSERT INTO @TargetReadings (PointNumber, Epoch, Easting, Northing) VALUES
('CB501', '2014-12-31T00:01:00', 528196.679, 178392.171),
('CB501', '2014-12-31T01:01:00', 528196.679, 178392.170),
('CB501', '2015-01-01T00:01:00', 528196.675, 178392.165),
('CB501', '2015-01-01T01:01:00', 528196.676, 178392.166),
('CB501', '2015-01-02T00:01:00', 528196.679, 178392.167),
('CB501', '2015-01-02T05:01:00', 528196.679, 178392.167);

<强>查询

SELECT
    R.PointNumber
    , R.Epoch
    , R.Easting + ISNULL(OA_Shift.ShiftEasting, 0) as ShiftEast
    , R.Northing + ISNULL(OA_Shift.ShiftNorthing, 0) as ShiftNorth
FROM
    @TargetReadings AS R
    OUTER APPLY
    (
        SELECT TOP(1)
            S.ShiftEasting
            , S.ShiftNorthing
        FROM @TargetShift AS S
        WHERE
            S.PointNumber = R.PointNumber
            AND S.Epoch < R.Epoch
        ORDER BY S.Epoch DESC
    ) OA_Shift
ORDER BY
    R.PointNumber
    , R.Epoch
;

<强>结果

PointNumber    Epoch                      ShiftEast     ShiftNorth
CB501          2014-12-31 00:01:00.000    528196.679    178392.171
CB501          2014-12-31 01:01:00.000    528196.679    178392.17
CB501          2015-01-01 00:01:00.000    628196.675    278392.165
CB501          2015-01-01 01:01:00.000    628196.676    278392.166
CB501          2015-01-02 00:01:00.000    728196.679    378392.167
CB501          2015-01-02 05:01:00.000    728196.679    378392.167

TargetReadings OUTER APPLY中的每一行都会找到TargetShift中有PointNumber的1行并且在TargetReadings行之前的日期。

如果您在TargetShift上向(PointNumber, Epoch DESC)添加索引,则查询应该有效。

答案 3 :(得分:0)

Mat,在我看来,你需要在targetShift中为每个具有max(epoch)的pointNumber输入,即最新的条目。实现此目的的一种方法是添加一个条件来过滤到targetShift表,例如:

SELECT 
    CASE WHEN a.Epoch > r.Epoch 
    THEN a.Easting + r.ShiftEasting
    END as ShiftEast
    , a.PointNumber
    , a.Epoch
    , r.Epoch
FROM
    TargetReadings a
    inner join targetShift r on r.PointNumber = a.PointNumber    
WHERE 
    r.epoch= (SELECT max(epoch) 
              FROM   targetShift r1 
              WHERE  r.Pointnumber=  r1.Pointnumber)

另一点:有意或无意,您的查询将只返回在targetShift中有一个或多个条目的TargetReadings - 可能不是必需的。