Pregunta

Ver nuevos e importantes descubrimientos 1 y 2, al final de esta explicación.

Estoy corriendo Postgres 9.1.3 y estoy teniendo un extraño left join problema.

Tengo una tabla llamada en consonancia.maestro con más de 2 millones de filas.Tiene una columna llamada citation_id, y que la columna no tiene valores nulos.Puedo comprobar que con esta:

SELECT COUNT(*)
FROM consistent.master
WHERE citation_id IS NULL

Que devuelve 0.

Aquí es donde se pone raro:si me LEFT JOIN esta tabla a una tabla temporal, me sale un error que estoy tratando de insertar un valor nulo en el citation_id campo:

ERROR:valor null en la columna "citation_id" viola los no-null constraint Estado de SQL:23502

Aquí está la consulta:

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

Estoy rascándome la cabeza en esto.Si se trata de un LEFT JOIN, y si en consonancia.maestro es la combinación de la tabla de la izquierda, ¿cómo podría esta consulta crear valores null en la citation_id columna cuando no hay, para empezar?

Aquí está el código SQL que he usado para crear la tabla:

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 );

DESCUBRIMIENTO IMPORTANTE 1

He descubierto algo interesante.Esta consulta:

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

Los resultados son:

2085344
2085343
0

¿Cómo puedo explicar eso?¿Cómo puede el contar con WHERE citation_id IS NOT NULL posiblemente sea mayor que la misma consulta sin WHERE cláusula?

IMPORTANTE DESCUBRIMIENTO 2 OK, por los comentarios de abajo, descubrí que tengo una fila con todos los valores vacíos, y esto es a pesar de el hecho de que la tabla tiene una serie id columna y algunos NOT NULL las limitaciones.

He eliminado el bum de la fila.Ahora no estoy recibiendo el error null.En lugar de eso, me estoy poniendo esto:

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.

Sólo para asegurarse de que, hago esta consulta:

SELECT COUNT(id)
FROM consistent.master
WHERE id=1583804;

¿Adivinen qué? consistent.master sólo tiene 1 ejemplo de esto!Por lo tanto, dado que la tabla de la izquierda en la LEFT JOIN sólo 1 instancia de 1583804 en citation_id y que el id columna sólo puede venir de la tabla de la izquierda, ¿cómo podría este error a suceder?Un LEFT JOIN como esto no debería causar el resultado final para tener más filas de la tabla de la izquierda, a la derecha?

¿Fue útil?

Solución

Con una INSERCIÓN, especialmente con un complejo de uno, usted debe siempre definir el destino de las columnas.Para hacer que:

INSERT INTO consistent.masternew (citation_id, col1, col2, ...)

Si algo va mal en el siguiente instrucción SELECT - como este:

the_geom geometry

(no tiene sentido cambiar el nombre de la columna con un tipo de nombre - supongo que esto no es intencionado) - o si el subyacente de la definición de la tabla de cambios, una instrucción INSERT sin destino definido columnas pueden ir terriblemente mal.

PostgreSQL no aplicar el mismo número de columnas en la instrucción SELECT en la tabla de destino.Cito la multa manual, en la que:

Cada columna no está presente en la explícita o implícita de columna de la lista ser llenado con un valor por defecto, en cualquiera de sus declarado valor predeterminado o null si no hay ninguno.

(En negrita el énfasis es mío.) Si usted tiene un desajuste en la columna de la lista, este puede ser un valor NULO aparecen "de la nada".

También, la orden de las columnas en la instrucción SELECT tiene que coincidir con el orden de las columnas para insertar en.Si las columnas de destino, no se dan, este sería el orden de las columnas en la tabla, ya que fue creado.
Se parecen esperar que las columnas se corresponden con el nombre de forma automática, pero que no es así.Los nombres de columna en la instrucción SELECT son completamente irrelevantes para el paso final de la INSERCIÓN.Sólo su orden de izquierda a derecha es significativa.

Contrario a lo que otros tienen implícita la CON la cláusula es perfectamente legítimo.Cito el manual en INSERTAR:

Es posible que la consulta (instrucción SELECT) para contener una CON la cláusula.En este caso ambos conjuntos de with_query se puede hacer referencia a dentro de la consulta, pero el segundo tiene prioridad, ya que es más estrechamente anidados.

Su declaración podría tener este aspecto:

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 (citation_id, col1, col2, ...) -- add columns
SELECT m.citation_id -- order colums accordingly!
      ,s.stop
      ,m.defendant_dl
        -- 27 more columns
      ,m.citing_jurisdiction
      ,m.the_geom
FROM   consistent.master m
LEFT   JOIN stops s USING (citation_id);

Otros consejos

En una adivinar, yo diría que son la inserción de las paradas.parada, que podría ser nulo, en el citation_id columna, pero sin conocer la estructura de la tabla que no puedo decir seguro :)

EDITAR:Trate de @vol7ron la sugerencia y el nombre de las columnas...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top