SQL帮助,用于为唯一工厂选择最新的非null值

时间:2019-03-31 16:24:43

标签: sql sql-server tsql

我有一个SQL Server表,其中包含有关各种工厂(工厂)的数据,并且行由根工厂ID和子工厂ID标识。设施的整个生命周期的根ID都是相同的。每次在监管机构更改工厂数据时,都会添加子ID。

有时向监管机构重新提交工厂数据时,仅提交更改的数据,而其他字段保留为空白(空)。

我正在寻找一种写查询的优雅方法,该查询将返回最近的子ID记录中的所有数据,但对于Capacity而言,它将拉取非null Capacity为实际指定。

假定这些是“植物”表中的字段:

  • RecordId(主键)
  • RootId
  • SubId
  • 燃油
  • 容量

以下是用于选择最新SubId数据的SQL:

SELECT p1.* FROM Plant as p1
WHERE 
    p1.SubId = (
            SELECT TOP 1 p2.SubId FROM Plant as p2 
            WHERE p1.RootId = p2.RootId
            ORDER BY p2.SubId DESC)

我已经考虑了一段时间,但是还没有想出办法。即使只是朝正确方向的推动,也将不胜感激。这是一些用于生成示例数据的SQL代码:

CREATE TABLE Plant (
    RecordId  INTEGER       PRIMARY KEY,
    RootId    VARCHAR(12)   not null,
    SubID     INTEGER    not null,
    Fuel      INTEGER   not null,
    Capacity  DECIMAL(10,4)
);


INSERT INTO Plant 
VALUES 
(451, 'PLT03-39', 3, 1, 4399.67),
(471, 'PLT03-39', 4, 1, 4399.67),
(1809, 'PLT03-39', 5, 1, 4399.67),
(4888, 'PLT03-39', 6, 1, Null),
(6111, 'PLT03-39', 7, 1, Null),
(450, 'PLT03-40', 3, 1, 15531.67),
(472, 'PLT03-40', 4, 1, Null),
(1810, 'PLT03-40', 5, 1, 14767.61),
(4882, 'PLT03-40', 6, 1, Null),
(6113, 'PLT03-40', 7, 1, Null),
(454, 'PLT03-41', 5, 1, 23726.34),
(455, 'PLT03-41', 6, 1, 23726.34),
(469, 'PLT03-41', 7, 1, 23726.34),
(1807, 'PLT03-41', 8, 1, 22850.96),
(4884, 'PLT03-41', 9, 1, 22850.96),
(6110, 'PLT03-41', 10, 1, 22850.96),
(452, 'PLT03-42', 3, 1, 9120.65),
(470, 'PLT03-42', 4, 1, Null),
(1808, 'PLT03-42', 5, 1, 9120.65),
(4883, 'PLT03-42', 6, 1, 9120.65),
(6109, 'PLT03-42', 7, 1, Null),
(449, 'PLT03-43', 4, 1, 7923.96),
(474, 'PLT03-43', 5, 1, 7923.96),
(1811, 'PLT03-43', 6, 1, 7357.24),
(4881, 'PLT03-43', 7, 1, Null),
(5107, 'PLT03-43', 7, 1, 7711.44),
(5133, 'PLT03-43', 7, 1, Null),
(6112, 'PLT03-43', 8, 1, 7711.44),
(98, 'PLT05-25', 2, 18, 26.565),
(528, 'PLT05-25', 2, 18, 26033.7),
(139, 'PLT05-25', 2, 18, 26565),
(380, 'PLT05-25', 2, 18, Null),
(381, 'PLT05-25', 2, 18, 51854.88),
(7398, 'PLT06-143', 0, 18, 4091.01),
(4112, 'PLT06-143', 1, 18, 4091.01),
(5309, 'PLT06-143', 2, 18, 4091.01),
(73982, 'PLT06-143', 2, 18, 4091.01),
(73981, 'PLT06-143', 3, 18, Null),
(7397, 'PLT06-145', 0, 18, 4091.01),
(73971, 'PLT06-145', 1, 18, 4091.01),
(4109, 'PLT06-145', 1, 18, Null),
(5314, 'PLT06-145', 2, 18, 4091.01),
(73972, 'PLT06-145', 2, 18, Null),
(73973, 'PLT06-145', 3, 18, 4091.01),
(177, 'PLT06-342', 2, 1, 35420),
(1307, 'PLT06-342', 3, 1, 30360),
(5946, 'PLT06-342', 4, 1, 30360),
(6220, 'PLT06-342', 5, 1, Null),
(13264, 'PLT06-342', 6, 1, Null),
(1312, 'PLT06-344', 2, 1, 15180),
(5106, 'PLT06-344', 3, 1, 15180),
(5945, 'PLT06-344', 4, 1, 15180),
(6218, 'PLT06-344', 5, 1, Null),
(10550, 'PLT06-344', 6, 1, 10120),
(13271, 'PLT06-344', 7, 1, 10120),
(2724, 'PLT06-87', 2, 6, 143.451),
(5039, 'PLT06-87', 3, 6, 143.451),
(5886, 'PLT06-87', 4, 6, Null),
(10586, 'PLT06-87', 5, 6, 143.451),
(22759, 'PLT06-87', 6, 6, Null),
(158, 'PLT07-234', 1, 18, 21274.77),
(341, 'PLT07-234', 2, 18, 21274.77),
(7813, 'PLT07-234', 3, 18, 21274.77),
(24562, 'PLT07-234', 4, 18, Null),
(24584, 'PLT07-234', 4, 18, 2488.508),
(5965, 'PLT07-328', 2, 1, 19607.5),
(6073, 'PLT07-328', 2, 1, 19607.5),
(5996, 'PLT07-328', 2, 1, 19607.5),
(6644, 'PLT07-328', 3, 1, 19607.5),
(6701, 'PLT07-328', 3, 1, Null),
(7664, 'PLT07-328', 4, 1, Null),
(227, 'PLT07-39', 2, 18, 50347),
(1269, 'PLT07-39', 3, 18, 50258.45),
(1821, 'PLT07-39', 4, 18, 50258.45),
(1976, 'PLT07-39', 4, 18, 50258.45),
(5282, 'PLT07-39', 5, 18, Null),
(374, 'PLT08-25', 2, 18, 55331.1),
(135, 'PLT08-25', 2, 18, 30.36),
(134, 'PLT08-25', 2, 18, 56.925),
(533, 'PLT08-25', 2, 18, 55.7865),
(93, 'PLT08-25', 2, 18, 56.925),
(4081, 'PLT08-437', 1, 18, 5206.74),
(4241, 'PLT08-437', 2, 18, 5206.74),
(4242, 'PLT08-437', 3, 18, 5206.74),
(4532, 'PLT08-437', 4, 18, 4946.656),
(24344, 'PLT08-437', 5, 18, Null),
(460, 'PLT10-574', 0, 18, 198207.284),
(943, 'PLT10-574', 2, 18, 198207.284),
(1248, 'PLT10-574', 3, 18, 198207.284),
(2371, 'PLT10-574', 4, 18, 198207.284),
(6173, 'PLT10-574', 5, 18, 198207.284),
(17787, 'PLT10-574', 6, 18, 198207.284),
(23533, 'PLT10-574', 7, 18, 198207.284)
;

这是我要查询的预期结果:

RecordId    RootId  SubId   Fuel    Capacity
6111    PLT03-39    7   1   4399.67
6113    PLT03-40    7   1   14767.61
6110    PLT03-41    10  1   22850.96
6109    PLT03-42    7   1   9120.65
6112    PLT03-43    8   1   7711.44
381 PLT05-25    2   18  51854.88
7398    PLT06-143   3   18  4091.01
7397    PLT06-145   3   18  4091.01
13264   PLT06-342   6   1   30360
13271   PLT06-344   7   1   10120
22759   PLT06-87    6   6   143.451
24584   PLT07-234   4   18  2488.508
7664    PLT07-328   4   1   19607.5
5282    PLT07-39    5   18  50258.45
93  PLT08-25    2   18  56.925
24344   PLT08-437   5   18  4946.656
23533   PLT10-574   7   18  198207.284

1 个答案:

答案 0 :(得分:1)

下面是解决此问题的一种方法。我使用CTEMAX聚合来确定每个RecordId的最新RootId。将其连接回Plant表之后,使用OUTER APPLY来检索最新容量。

WITH LATEST AS
(
    SELECT RootId, MAX(RecordId) AS RecordId
    FROM Plant
    GROUP BY RootId
)

SELECT
    P.RecordId
    , P.RootId
    , P.SubID
    , P.Fuel
    , CAP.Capacity
FROM
    LATEST AS L
    JOIN Plant AS P
        ON L.RecordId = P.RecordId
    OUTER APPLY
        (
            SELECT TOP 1 Capacity
            FROM Plant
            WHERE RootId = P.RootId AND Capacity IS NOT NULL
            ORDER BY SubID DESC
        ) AS CAP
ORDER BY
    L.RootId