Pregunta

Tengo filas en una tabla de base de datos Oracle que debe ser único para una combinación de dos campos, pero la única restricción no está configurado en la mesa, así que necesito para encontrar todas las filas que violan la restricción a mí mismo usando SQL. Desafortunadamente mis conocimientos de SQL magros no están a la altura.

Mi tabla tiene tres columnas que son relevantes: entity_id, station_id y obs_year. Para cada fila de la combinación de station_id y obs_year debe ser único, y quiero saber si hay filas que violan este por lavado fuera con una consulta SQL.

He probado el siguiente código SQL (sugerido por esta pregunta anterior ) pero no funciona para mí (me da ORA-00918 columna ambiguamente definido):

SELECT
entity_id, station_id, obs_year
FROM
mytable t1
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable 
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes 
ON 
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year

Puede alguien sugerir lo que estoy haciendo mal, y / o la forma de resolver esto?

¿Fue útil?

Solución

SELECT  *
FROM    (
        SELECT  t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn
        FROM    mytable t
        )
WHERE   rn > 1

Otros consejos

SELECT entity_id, station_id, obs_year
FROM mytable t1
WHERE EXISTS (SELECT 1 from mytable t2 Where
       t1.station_id = t2.station_id
       AND t1.obs_year = t2.obs_year
       AND t1.RowId <> t2.RowId)

Cambiar los 3 campos en el selecto inicial sea

SELECT
t1.entity_id, t1.station_id, t1.obs_year

Re-escritura de la consulta

SELECT
t1.entity_id, t1.station_id, t1.obs_year
FROM
mytable t1
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable 
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes 
ON 
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year

Creo que el error de la columna ambigua (ORA-00918) era porque estabas selecting columnas cuyos nombres aparecían en la tabla y la subconsulta, pero no se hizo specifiy si querías de dupes o desde mytable (alias, tal como t1) .

Podría no crear una nueva tabla que incluye la restricción única, y luego copiar los datos en la fila por fila, haciendo caso omiso de los fallos?

Es necesario especificar la tabla de las columnas de la principal selección. Además, en el supuesto entity_id es la clave única para mitabla y es irrelevante para la búsqueda de duplicados, que no se debe agrupar en el que en la sub consulta duplicados.

Trate:

SELECT t1.entity_id, t1.station_id, t1.obs_year
FROM mytable t1
INNER JOIN (
SELECT station_id, obs_year FROM mytable 
GROUP BY station_id, obs_year HAVING COUNT(*) > 1) dupes 
ON 
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year
SELECT  *
FROM    (
        SELECT  t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn
        FROM    mytable t
        )
WHERE   rn > 1

por Quassnoi es el más eficiente para tablas grandes. Tenía este análisis de costo:

SELECT a.dist_code, a.book_date, a.book_no
FROM trn_refil_book a
WHERE EXISTS (SELECT 1 from trn_refil_book b Where
       a.dist_code = b.dist_code and a.book_date = b.book_date and a.book_no = b.book_no
       AND a.RowId <> b.RowId)
       ;

dio un coste de 1.322.341

SELECT a.dist_code, a.book_date, a.book_no
FROM trn_refil_book a
INNER JOIN (
SELECT b.dist_code, b.book_date, b.book_no FROM trn_refil_book b 
GROUP BY b.dist_code, b.book_date, b.book_no HAVING COUNT(*) > 1) c 
ON 
 a.dist_code = c.dist_code and a.book_date = c.book_date and a.book_no = c.book_no
;

dio un coste de 1.271.699

mientras

SELECT  dist_code, book_date, book_no
FROM    (
        SELECT  t.dist_code, t.book_date, t.book_no, ROW_NUMBER() OVER (PARTITION BY t.book_date, t.book_no
          ORDER BY t.dist_code) AS rn
        FROM    trn_refil_book t
        ) p
WHERE   p.rn > 1
;

dio un coste de 1021984

La mesa no fue indexada ....

  SELECT entity_id, station_id, obs_year
    FROM mytable
GROUP BY entity_id, station_id, obs_year
HAVING COUNT(*) > 1

Especificar los campos para encontrar duplicados tanto en el SELECT y el GROUP BY.

Funciona mediante el uso GROUP BY para encontrar las filas que coincidan con cualquier otro filas sobre la base de las columnas especificadas. El HAVING COUNT(*) > 1 dice que sólo estamos interesados ??en ver las filas que se producen más de 1 vez (y por lo tanto son duplicados)

pensé que muchas de las soluciones de aquí es engorroso y difícil de entender, ya que tenía una restricción de clave primaria 3 y la columna tenía que encontrar los duplicados. Así que aquí hay una opción

SELECT id, name, value, COUNT(*) FROM db_name.table_name
GROUP BY id, name, value
HAVING COUNT(*) > 1
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top