Справка по SQL для выбора самого последнего ненулевого значения для уникального завода - PullRequest
2 голосов
/ 31 марта 2019

У меня есть таблица SQL Server с данными о различных фабриках (заводах), со строками, идентифицированными по идентификатору корневого предприятия и идентификатору подстанции.Идентификатор root одинаков для всего объекта.И дополнительный идентификатор добавляется каждый раз, когда данные завода изменяются регулирующим органом.

Иногда, когда данные завода были повторно переданы в регулятор, были представлены только измененные данные, а другие поля оставались пустыми.(Null).

Я ищу элегантный способ написать запрос, который будет возвращать все данные из самой последней записи идентификатора sub, за исключением того, что для Capacity он будет извлекать самый последний sub длякоторый на самом деле был задан ненулевой емкостью.

Предположим, что это поля таблицы Plant:

  • RecordId (первичный ключ)
  • RootId
  • SubId
  • Топливо
  • Емкость

Вот SQL для выбора данных для самого последнего SubId:

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 Ответ

1 голос
/ 31 марта 2019

Ниже приведено одно решение этой проблемы. Я использовал совокупности CTE и MAX , чтобы определить самые последние значения 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...