SQL наибольший n-на-группу с точными данными по нескольким таблицам - PullRequest
0 голосов
/ 28 июля 2011

У меня проблема с наибольшим числом групп, которую я пытаюсь решить. Я просматривал существующие решения, но ни одно из них не соответствует причудам, с которыми я имею дело.

Сценарий: Скажем, есть нефтяная компания, у которой есть коллекция нефтяных скважин. В каждой скважине есть несколько нефтяных резервуаров. Каждый день кто-то читает по каждой лунке. Иногда они также снимают показания резервуаров, однако показания резервуаров встречаются гораздо реже и могут распространяться на несколько дней.

Все показания скважины и резервуара заносятся в базу данных, упорядоченную по дате.

CREATE TABLE "wellReadings" (
    "id" INT PRIMARY AUTO_INCREMENT,
    "date" DATETIME,
    "wellName" VARCHAR(10),
    ...
);

CREATE TABLE "tankReadings" (
    "id" INT PRIMARY AUTO_INCREMENT,
    "date" DATETIME,
    "well" INT NOT NULL,
    "tankName" VARCHAR(10),
    ...
);

Проблема: Для любого заданного показания скважины (в таблице wellReadings) на любую заданную дату я хочу найти показания резервуара (в таблице tankReadings) для всех резервуаров, связанных с этой скважиной, взятый в тот же день. Если конкретный танк не имеет показаний на эту дату, я хочу получить самые последние показания до этой даты.

До сих пор я пытался использовать объединения и подзапросы, но не смог сузить результаты до самого последнего показания резервуара (мои тестовые запросы постоянно дают мне ВСЕ показания резервуара, которые происходят во время или перед хорошо читаю дату). Коррелированный подзапрос может работать, но моя БД их не поддерживает (SQLite).

1 Ответ

1 голос
/ 28 июля 2011

Вы всегда можете попробовать что-то вроде:

SELECT * FROM wellReadings AS well, tankReadings AS tank
 WHERE tank.well = well.id 
   AND tank.date =
       (SELECT MAX(tank2.date) FROM tankReadings AS tank2
         WHERE tank2.id = tank.id
           AND tank2.date <= well.date)

Возможно, это не самый эффективный способ сделать это, но он должен работать.

Ps.Если возможно, что в некоторых скважинах вообще нет показаний прошлых резервуаров, вы можете вместо этого использовать левое соединение:

SELECT * FROM wellReadings AS well
  LEFT JOIN tankReadings AS tank
    ON tank.well = well.id 
   AND tank.date =
       (SELECT MAX(tank2.date) FROM tankReadings AS tank2
         WHERE tank2.id = tank.id
           AND tank2.date <= well.date)
...