См. Важные новые открытия 1 и 2. В конце этого объяснения.
Я использую Postgres 9.1.3 и у меня странная проблема с левым соединением.
У меня есть таблица с именем последовательный. Мастер с более чем 2 миллионами строк.Он имеет столбец с именем citation_id , и этот столбец не имеет нулевых значений.Я могу убедиться в этом:
SELECT COUNT(*)
FROM consistent.master
WHERE citation_id IS NULL
Это возвращает 0 .
Вот где это становится странным: если я LEFT JOIN эта таблицаво временную таблицу я получаю сообщение об ошибке, что я пытаюсь вставить нулевое значение в поле citation_id :
ОШИБКА: нулевое значение в столбце "citation_id" нарушает ненулевое значениеСостояние SQL ограничения: 23502
Вот запрос:
WITH stops AS (
SELECT citation_id,
rank() OVER (ORDER BY offense_timestamp,
defendant_dl,
offense_street_number,
offense_street_name) AS stop
FROM consistent.master
WHERE citing_jurisdiction=1
)
INSERT INTO consistent.masternew (arrest_id, citation_id, defendant_dl, defendant_dl_state, defendant_zip, defendant_race, defendant_sex, defendant_dob, vehicle_licenseplate, vehicle_licenseplate_state, vehicle_registration_expiration_date, vehicle_year, vehicle_make, vehicle_model, vehicle_color, offense_timestamp, offense_street_number, offense_street_name, offense_crossstreet_number, offense_crossstreet_name, offense_county, officer_id, offense_code, speed_alleged, speed_limit, work_zone, school_zone, offense_location, id, source, citing_jurisdiction, the_geom)
SELECT stops.stop, master.citation_id, defendant_dl, defendant_dl_state, defendant_zip, defendant_race, defendant_sex, defendant_dob, vehicle_licenseplate, vehicle_licenseplate_state, vehicle_registration_expiration_date, vehicle_year, vehicle_make, vehicle_model, vehicle_color, offense_timestamp, offense_street_number, offense_street_name, offense_crossstreet_number, offense_crossstreet_name, offense_county, officer_id, offense_code, speed_alleged, speed_limit, work_zone, school_zone, offense_location, id, source, citing_jurisdiction, the_geom
FROM consistent.master LEFT JOIN stops
ON stops.citation_id = master.citation_id
Я почесываю голову об этом.Если это LEFT JOIN , и если compatibility.master является левой таблицей объединения, как этот запрос может создать нулевые значения в столбце citation_id , если его нет?
Вот код SQL, который я использовал для создания таблицы:
CREATE TABLE consistent.masternew
(
arrest_id character varying(20),
citation_id character varying(20) NOT NULL,
defendant_dl character varying(20),
defendant_dl_state character varying(2),
defendant_zip character varying(9),
defendant_race character varying(10),
defendant_sex character(1),
defendant_dob date,
vehicle_licenseplate character varying(10),
vehicle_licenseplate_state character(2),
vehicle_registration_expiration_date date,
vehicle_year integer,
vehicle_make character varying(20),
vehicle_model character varying(20),
vehicle_color character varying,
offense_timestamp timestamp without time zone,
offense_street_number character varying(10),
offense_street_name character varying(30),
offense_crossstreet_number character varying(10),
offense_crossstreet_name character varying(30),
offense_county character varying(10),
officer_id character varying(20),
offense_code integer,
speed_alleged integer,
speed_limit integer,
work_zone bit(1),
school_zone bit(1),
offense_location point,
id serial NOT NULL,
source character varying(20), -- Where this citation came from--court, PD, etc.
citing_jurisdiction integer,
the_geom geometry,
CONSTRAINT masternew_pkey PRIMARY KEY (id ),
CONSTRAINT citing_jurisdiction FOREIGN KEY (citing_jurisdiction)
REFERENCES consistent.jurisdictions (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT offenses FOREIGN KEY (offense_code)
REFERENCES consistent.offenses (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT enforce_dims_the_geom CHECK (st_ndims(the_geom) = 2),
CONSTRAINT enforce_geotype_the_geom CHECK (geometrytype(the_geom) = 'POINT'::text OR the_geom IS NULL),
CONSTRAINT enforce_srid_the_geom CHECK (st_srid(the_geom) = 3081)
)
WITH (
OIDS=FALSE
);
ALTER TABLE consistent.masternew
OWNER TO postgres;
COMMENT ON COLUMN consistent.masternew.source IS 'Where this citation came from--court, PD, etc.';
CREATE INDEX masternew_citation_id_idx
ON consistent.masternew
USING btree
(citation_id COLLATE pg_catalog."default" );
CREATE INDEX masternew_citing_jurisdiction_idx
ON consistent.masternew
USING btree
(citing_jurisdiction );
CREATE INDEX masternew_defendant_dl_idx
ON consistent.masternew
USING btree
(defendant_dl COLLATE pg_catalog."default" );
CREATE INDEX masternew_id_idx
ON consistent.masternew
USING btree
(id );
CREATE INDEX masternew_offense_street_name_idx
ON consistent.masternew
USING btree
(offense_street_name COLLATE pg_catalog."default" );
CREATE INDEX masternew_offense_street_number_idx
ON consistent.masternew
USING btree
(offense_street_number COLLATE pg_catalog."default" );
CREATE INDEX masternew_offense_timestamp_idx
ON consistent.masternew
USING btree
(offense_timestamp );
CREATE INDEX masternew_the_geom_idx
ON consistent.masternew
USING gist
(the_geom );
ВАЖНОЕ ОТКРЫТИЕ 1
Я простообнаружил что-то интересное.Этот запрос:
SELECT COUNT(*)
FROM consistent.master
WHERE citation_id IS NOT NULL
UNION
SELECT COUNT(*)
FROM consistent.master
UNION
SELECT COUNT(*)
FROM consistent.master
WHERE citation_id IS NULL
Результаты:
2085344
2085343
0
Как я могу это объяснить?Как может счет с WHERE citation_id IS NOT NULL
возможно быть выше, чем тот же запрос без предложения WHERE
?
ВАЖНОЕ ОТКРЫТИЕ 2 ОК, согласно комментариям ниже, я обнаружил, что у меня естьстрока со всеми пустыми значениями, и это несмотря на тот факт, что в таблице есть последовательный столбец id
и некоторые ограничения NOT NULL
.
Я удалил строку задницы.Теперь я не получаю нулевую ошибку.Вместо этого я получаю это:
ERROR: duplicate key value violates unique constraint "masternew_pkey"
DETAIL: Key (id)=(1583804) already exists.
********** Error **********
ERROR: duplicate key value violates unique constraint "masternew_pkey"
SQL state: 23505
Detail: Key (id)=(1583804) already exists.
Итак, просто чтобы убедиться, что я делаю этот запрос:
SELECT COUNT(id)
FROM consistent.master
WHERE id=1583804;
Угадайте что?consistent.master
имеет только 1 экземпляр этого!Таким образом, учитывая, что левая таблица в LEFT JOIN
только 1 экземпляре 1583804 в citation_id
и , столбец id может исходить только из левой таблицыКак эта ошибка может произойти?Подобное LEFT JOIN
не должно приводить к тому, что в конечном результате будет больше строк, чем в левой таблице, верно?