tablas - transponer filas en columnas mysql
¿Cómo puedo(o puedo) SELECCIONAR DISTINCIÓN en varias columnas? (4)
El problema con su consulta es que cuando usa una cláusula GROUP BY (lo que básicamente hace usando distintas), solo puede usar columnas que agrupe o agregue funciones. No puede usar el ID de columna porque hay valores potencialmente diferentes. En su caso, siempre hay un solo valor debido a la cláusula HAVING, pero la mayoría de los RDBMS no son lo suficientemente inteligentes como para reconocerlo.
Esto debería funcionar sin embargo (y no necesita una combinación):
UPDATE sales
SET status=''ACTIVE''
WHERE id IN (
SELECT MIN(id) FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(id) = 1
)
También puede usar MAX o AVG en lugar de MIN, solo es importante usar una función que devuelva el valor de la columna si solo hay una fila coincidente.
Necesito recuperar todas las filas de una tabla donde 2 columnas combinadas son todas diferentes. Así que quiero todas las ventas que no tengan ninguna otra venta que haya tenido lugar el mismo día por el mismo precio. Las ventas que son únicas según el día y el precio se actualizarán a un estado activo.
Así que estoy pensando:
UPDATE sales
SET status = ''ACTIVE''
WHERE id IN (SELECT DISTINCT (saleprice, saledate), id, count(id)
FROM sales
HAVING count = 1)
Pero mi cerebro duele yendo más allá de eso.
Quiero seleccionar los valores distintos de una columna ''GrondOfLucht'', pero deberían ordenarse en el orden que se indica en la columna ''clasificación''. No puedo obtener los valores distintos de una sola columna usando
Select distinct GrondOfLucht,sortering
from CorWijzeVanAanleg
order by sortering
También le dará a la columna "clasificación" y como "GrondOfLucht" Y "clasificación" no son únicos, el resultado serán TODAS las filas.
Use el GRUPO para seleccionar los registros de ''GrondOfLucht'' en el orden dado por ''clasificador
SELECT GrondOfLucht
FROM dbo.CorWijzeVanAanleg
GROUP BY GrondOfLucht, sortering
ORDER BY MIN(sortering)
Si reúne las respuestas hasta el momento, limpie y mejore, llegará a esta consulta superior:
UPDATE sales
SET status = ''ACTIVE''
WHERE (saleprice, saledate) IN (
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING count(*) = 1
);
Que es mucho más rápido que cualquiera de ellos. Nukes el rendimiento de la respuesta actualmente aceptada por el factor 10 - 15 (en mis pruebas en PostgreSQL 8.4 y 9.1).
Pero esto aún está lejos de ser óptimo. Utilice una semi-unión NOT EXISTS
(anti) para obtener un rendimiento aún mejor. EXISTS
es un SQL estándar, ha existido desde siempre (al menos desde PostgreSQL 7.2, mucho antes de que se hiciera esta pregunta) y se ajusta perfectamente a los requisitos presentados:
UPDATE sales s
SET status = ''ACTIVE''
WHERE NOT EXISTS (
SELECT 1
FROM sales s1
WHERE s.saleprice = s1.saleprice
AND s.saledate = s1.saledate
AND s.id <> s1.id -- except for row itself
);
AND s.status IS DISTINCT FROM ''ACTIVE''; -- avoid empty updates. see below
Clave única para identificar la fila
Si no tiene una clave principal o única para la tabla ( id
en el ejemplo), puede sustituirla con la columna del sistema ctid
para el propósito de esta consulta (pero no para otros propósitos):
AND s1.ctid <> s.ctid
Cada tabla debe tener una clave primaria. Agrega uno si aún no tienes uno. Sugiero una columna de serial
o IDENTITY
en Postgres 10+.
Relacionado:
¿Cómo es esto más rápido?
La subconsulta en la anti-semi-unión EXISTS
puede dejar de evaluar tan pronto como se encuentre la primera duplicidad (no tiene sentido mirar más allá). Para una tabla base con pocos duplicados, esto es solo ligeramente más eficiente. Con muchos duplicados esto se vuelve mucho más eficiente.
Excluir actualizaciones vacías
Si algunas o muchas filas ya tienen el status = ''ACTIVE''
, su actualización no cambiará nada, pero aún así insertará una nueva versión de la fila a un costo total (se aplican excepciones menores). Normalmente, no quieres esto. Agregue otra condición WHERE
como se demostró anteriormente para hacer esto aún más rápido:
Si el status
se define como NOT NULL
, puede simplificar a:
AND status <> ''ACTIVE'';
Diferencia sutil en el manejo NULL
Esta consulta (a diferencia de la respuesta actualmente aceptada por Joel ) no trata los valores NULL como iguales. Estas dos filas para (saleprice, saledate)
calificarían como "distintas" (aunque parecen idénticas al ojo humano):
(123, NULL)
(123, NULL)
También pasa en un índice único y casi en cualquier otro lugar, ya que los valores NULL no se comparan de acuerdo con el estándar SQL. Ver:
OTOH, GROUP BY
o DISTINCT
o DISTINCT ON ()
tratan los valores NULL como iguales. Utilice un estilo de consulta adecuado en función de lo que desea lograr. Aún puede usar este estilo de consulta más rápido usando IS NOT DISTINCT FROM
lugar de =
para cualquiera o todas las comparaciones para hacer que NULL compare igual. Más:
Si todas las columnas que se comparan están definidas como NOT NULL
, no hay espacio para el desacuerdo.
SELECT DISTINCT a,b,c FROM t
es aproximadamente equivalente a:
SELECT a,b,c FROM t GROUP BY a,b,c
Es una buena idea acostumbrarse a la sintaxis de GROUP BY, ya que es más potente.
Para tu consulta, lo haría así:
UPDATE sales
SET status=''ACTIVE''
WHERE id IN
(
SELECT id
FROM sales S
INNER JOIN
(
SELECT saleprice, saledate
FROM sales
GROUP BY saleprice, saledate
HAVING COUNT(*) = 1
) T
ON S.saleprice=T.saleprice AND s.saledate=T.saledate
)