0

My tables track changes in event variables and state variables. I would like to be able to easily make a query where I get events that occur only when the state variable at that time meets a certain condition. The problem I have is that the timestamps for the events and the states don't align exactly. Rather, the state variable entry with the timestamp most recent relative to the event timestamp should be checked. I could append all the state variables to all my event entries, but this would make my database many times larger.

My question is whether there is a more efficient way to make the following query. Ideally, I think, I would like the timestamp in my state variables to be indexed so that it can be accessed using any value from it's stated value up to the next timestamp. The timestamps are in strictly ascending order.

Edit: Here are example tables included as well.

CREATE TABLE event
(
  tickstamp integer NOT NULL,
  value integer,
  CONSTRAINT event_pkey PRIMARY KEY (tickstamp)
);

INSERT INTO event VALUES
  (121, 100),
  (152, 75),
  (194, 150);

Create TABLE state
(
  tickstamp integer NOT NULL,
  value integer,
  CONSTRAINT state_pkey PRIMARY KEY (tickstamp)
);

INSERT INTO state VALUES
  (0, 30),
  (160, 95);

SELECT * FROM event, state
WHERE state.value > 50 AND state.tickstamp = (
    SELECT tickstamp FROM state WHERE tickstamp <= event.tickstamp ORDER BY tickstamp DESC LIMIT 1);

Really, all I care about here is filtering events so that state.value > 50 when the event occurs, which is only true for the third entry in event, but I have to do a subquery in order to match up the tickstamps.

2
  • 1
    please add table definition and sample data. BTW: timestamp is a bad name for a column. Commented Mar 9, 2016 at 22:35
  • I added some sample tables/data. Hopefully enough to better demonstrate what I'm trying to do. The actual name of my column is tickstamp, which I hope is ok. Commented Mar 9, 2016 at 23:07

2 Answers 2

0
SELECT * FROM event, state
WHERE state.value > 50 AND state.tickstamp = (
    SELECT MAX(tickstamp) FROM state WHERE tickstamp <= event.tickstamp);

of course, if tickstamp isn't indexed, it'll likely still require a tablescan. Better solution is to have an auto-incremented field as your index and look for max.

6
  • This looks like an improvement, but still seems cumbersome for what will be a standard lookup for the table. Is there no way to create an index that maps a range to the row so that I can just do something like state.tickstamp = event.tickstamp rather than doing a subquery? Commented Mar 9, 2016 at 23:30
  • it is, but if the data model is immutable, there's not many ways to approach this...if the data model is up for grabs, there's much better designs that can simplify all of it.... Commented Mar 10, 2016 at 0:19
  • I'm definitely open to suggestions regarding the data model. The only thing I really want to avoid is creating an extra events * states entries. Commented Mar 10, 2016 at 1:48
  • Foreign keys are your friends. I'm assuming as events are processed that the state is updated in parallel, the best way would to add an event FK in the state table and associate the state with the event that triggered the state. Then navigate the FK and you'll immediately be able to get both aligned correctly. Commented Mar 10, 2016 at 2:11
  • You're right that events and states are updated in parallel, but unfortunately I need to be able to look up all states from all events, not just the events that trigger the specific state change. If I understand your suggestion correctly, I would only be able to look up the states that each event directly changes. Each state variable has its own table and each event has its own table, in case that wasn't clear. Commented Mar 10, 2016 at 3:34
0

I was able to solve this using the postgres range type.

CREATE TABLE event
(
  tickstamp int8range NOT NULL,
  value integer,
  CONSTRAINT event_pkey PRIMARY KEY (tickstamp)
);

INSERT INTO event VALUES
  ('[121,152)', 100),
  ('[152,194)', 75),
  ('[194,)', 150);

Create TABLE state
(
  tickstamp int8range NOT NULL,
  value integer,
  CONSTRAINT state_pkey PRIMARY KEY (tickstamp)
);

INSERT INTO state VALUES
  ('[0,160)', 30),
  ('[160,)', 95);

SELECT * FROM event, state
WHERE state.value > 50 AND event.tickstamp <@ state.tickstamp;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.