Cómo seleccionar solo las primeras filas para cada valor único de una columna


Digamos que tengo una tabla de direcciones de clientes:

CName           |   AddressLine
-------------------------------
John Smith      | 123 Nowheresville
Jane Doe        | 456 Evergreen Terrace
John Smith      | 999 Somewhereelse
Joe Bloggs      | 1 Second Ave

En la tabla, un cliente como John Smith puede tener varias direcciones. Necesito que la consulta select para esta tabla devuelva solo la primera fila encontrada donde hay duplicados en 'CName'. Para esta tabla debe devolver todas las filas excepto la 3ra(o 1ra-cualquiera de esas dos direcciones están bien, pero solo se puede devolver una). ¿Hay una palabra clave que pueda agregar a la consulta SELECT para filtrar en función de si el servidor ya ha visto valor de la columna antes?

Author: essential, 2011-01-11

5 answers

Una respuesta muy simple si dices que no te importa qué dirección se usa.

SELECT
    CName, MIN(AddressLine)
FROM
    MyTable
GROUP BY
    CName

Si desea la primera de acuerdo con, digamos, una columna "insertada", entonces es una consulta diferente

SELECT
    M.CName, M.AddressLine,
FROM
    (
    SELECT
        CName, MIN(Inserted) AS First
    FROM
        MyTable
    GROUP BY
        CName
    ) foo
    JOIN
    MyTable M ON foo.CName = M.CName AND foo.First = M.Inserted
 92
Author: gbn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-11 20:50:45

En SQL 2k5+, puedes hacer algo como:

;with cte as (
  select CName, AddressLine,
  rank() over (partition by CName order by AddressLine) as [r]
  from MyTable
)
select CName, AddressLine
from cte
where [r] = 1
 20
Author: Ben Thul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-22 00:49:13

Puede usar row_number() para obtener el número de fila de la fila. Utiliza el comando over - la cláusula partition by especifica cuándo reiniciar la numeración y el order by selecciona en qué ordenar el número de fila. Incluso si agregara un order by al final de su consulta, conservaría el orden en el comando over al numerar.

select *
from mytable
where row_number() over(partition by Name order by AddressLine) = 1
 9
Author: Rizzi Frank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-19 18:32:48

Puedes usar la sintaxis row_numer() over(partition by ...) así:

select * from
(
select *
, ROW_NUMBER() OVER(PARTITION BY CName ORDER BY AddressLine) AS row
from myTable
) as a
where row = 1

Lo que esto hace es que crea una columna llamada row, que es un contador que aumenta cada vez que ve el mismo CName, e indexa esas ocurrencias por AddressLine. Al imponer where row = 1, se puede seleccionar el CName cuyo AddressLine viene primero alfabéticamente. Si el order by era desc, entonces elegiría el CName cuyo AddressLine viene último alfabéticamente.

 2
Author: FatihAkici,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-01 11:49:00

Esto le dará una fila de cada fila duplicada. También le dará las columnas de tipo bit, y funciona al menos en MS Sql Server.

(select cname, address 
from (
  select cname,address, rn=row_number() over (partition by cname order by cname) 
  from customeraddresses  
) x 
where rn = 1) order by cname

Si desea encontrar todos los duplicados en su lugar, simplemente cambie el rn= 1 a rn > 1. Espero que esto ayude

 0
Author: netfed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-09 00:26:15