CREATE TABLE metadata.tenants ( id BIGINT PRIMARY KEY DEFAULT nextval('tenants_id_seq'), name VARCHAR(100) NOT NULL UNIQUE, -- Company details company_name VARCHAR(200), legal_name VARCHAR(200), tax_id VARCHAR(50), -- Address address TEXT, city VARCHAR(100), country VARCHAR(100), postal_code VARCHAR(20), -- Contact phone VARCHAR(30), email VARCHAR(100), website VARCHAR(255), -- Metadata industry VARCHAR(100), is_active BOOLEAN NOT NULL DEFAULT TRUE, -- Audit created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW());CREATE INDEX idx_tenants_active ON metadata.tenants(is_active);CREATE INDEX idx_tenants_name ON metadata.tenants(name);
Show greenhouses table
CREATE TABLE metadata.greenhouses ( id BIGINT PRIMARY KEY DEFAULT nextval('greenhouses_id_seq'), tenant_id BIGINT NOT NULL REFERENCES tenants(id) ON DELETE CASCADE, -- Identification name VARCHAR(100) NOT NULL, greenhouse_code VARCHAR(50) UNIQUE, description TEXT, -- Location location_coordinates GEOGRAPHY(POINT, 4326), timezone VARCHAR(50) DEFAULT 'Europe/Madrid', -- Physical properties area_m2 NUMERIC(10,2), greenhouse_type VARCHAR(50), -- MQTT configuration mqtt_topic VARCHAR(100), -- Status is_active BOOLEAN NOT NULL DEFAULT TRUE, -- Audit created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT uq_greenhouse_tenant_name UNIQUE (tenant_id, name));CREATE INDEX idx_greenhouses_tenant ON metadata.greenhouses(tenant_id);CREATE INDEX idx_greenhouses_active ON metadata.greenhouses(is_active);CREATE INDEX idx_greenhouses_tenant_active ON metadata.greenhouses(tenant_id, is_active);
Show devices table (unified sensors + actuators)
CREATE TABLE metadata.devices ( id BIGINT PRIMARY KEY DEFAULT nextval('devices_id_seq'), tenant_id BIGINT NOT NULL REFERENCES tenants(id) ON DELETE CASCADE, greenhouse_id BIGINT NOT NULL REFERENCES greenhouses(id) ON DELETE CASCADE, -- Identification catalog_id VARCHAR(100) NOT NULL, -- Hardware ID (ESP32_TEMP_001) name VARCHAR(100) NOT NULL, description TEXT, -- Device type device_type_id INTEGER NOT NULL REFERENCES device_types(id), category_id SMALLINT NOT NULL REFERENCES device_categories(id), -- MQTT configuration mqtt_topic VARCHAR(100), -- Status is_active BOOLEAN NOT NULL DEFAULT TRUE, last_seen_at TIMESTAMPTZ, -- Metadata metadata JSONB, -- Audit created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT uq_device_catalog_id UNIQUE (catalog_id));CREATE INDEX idx_devices_tenant ON metadata.devices(tenant_id);CREATE INDEX idx_devices_greenhouse ON metadata.devices(greenhouse_id);CREATE INDEX idx_devices_type ON metadata.devices(device_type_id);CREATE INDEX idx_devices_active ON metadata.devices(is_active);
Show sectors table (greenhouse subdivisions)
CREATE TABLE metadata.sectors ( id BIGINT PRIMARY KEY DEFAULT nextval('sectors_id_seq'), greenhouse_id BIGINT NOT NULL REFERENCES greenhouses(id) ON DELETE CASCADE, -- Identification sector_code VARCHAR(20) NOT NULL, name VARCHAR(100) NOT NULL, description TEXT, -- Physical properties area_m2 NUMERIC(10,2), location_data JSONB, -- Sector type sector_type VARCHAR(30) CHECK ( sector_type IN ('PRODUCTION', 'NURSERY', 'STORAGE', 'IRRIGATION_ZONE', 'CLIMATE_ZONE', 'OTHER') ), -- Crop information crop_type VARCHAR(100), crop_stage VARCHAR(30) CHECK ( crop_stage IN ('SEEDLING', 'VEGETATIVE', 'FLOWERING', 'FRUITING', 'HARVEST', 'DORMANT') ), -- Target conditions target_temperature_min NUMERIC(5,2), target_temperature_max NUMERIC(5,2), target_humidity_min NUMERIC(5,2), target_humidity_max NUMERIC(5,2), -- Status is_active BOOLEAN NOT NULL DEFAULT TRUE, -- Audit created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT uq_sector_code_per_greenhouse UNIQUE (greenhouse_id, sector_code), CONSTRAINT uq_sector_name_per_greenhouse UNIQUE (greenhouse_id, name));CREATE INDEX idx_sectors_greenhouse ON metadata.sectors(greenhouse_id);CREATE INDEX idx_sectors_active ON metadata.sectors(greenhouse_id, is_active);
-- ✅ Filter by time + device_id (indexed)SELECT time, valueFROM iot.readingsWHERE device_id = 123 AND time >= NOW() - INTERVAL '1 day'ORDER BY time DESCLIMIT 100;