una texto numeros len left hasta extraer ejemplos charindex caracteres caracter cadena buscar sql sql-server tsql join greatest-n-per-group

texto - sql substring hasta un caracter



SQL Left Únase solo a la primera coincidencia (6)

Agregue una columna de identidad (PeopleID) y luego use una subconsulta correlacionada para devolver el primer valor para cada valor.

SELECT * FROM People p WHERE PeopleID = ( SELECT MIN(PeopleID) FROM People WHERE IDNo = p.IDNo )

Tengo una consulta en contra de un gran número de tablas grandes (filas y columnas) con un número de combinaciones, sin embargo, una de las tablas tiene algunas filas duplicadas de datos que causan problemas para mi consulta. Como este es un feed de solo lectura en tiempo real de otro departamento, no puedo corregir esos datos, sin embargo, estoy tratando de evitar problemas en mi consulta.

Teniendo en cuenta eso, necesito agregar esta basura de datos como un enlace izquierdo a mi buena consulta. El conjunto de datos se ve así:

IDNo FirstName LastName ... ------------------------------------------- uqx bob smith abc john willis ABC john willis aBc john willis WTF jeff bridges sss bill doe ere sally abby wtf jeff bridges ...

(alrededor de 2 docenas de columnas y 100K filas)

Mi primer instinto fue realizar un distinto me dio sobre 80K filas:

SELECT DISTINCT P.IDNo FROM people P

Pero cuando intento lo siguiente, recupero todas las filas:

SELECT DISTINCT P.* FROM people P

O

SELECT DISTINCT(P.IDNo) AS IDNoUnq ,P.FirstName ,P.LastName ...etc. FROM people P

Entonces pensé que haría una función global FIRST () en todas las columnas, sin embargo, eso también parece estar mal. ¿Sintácticamente estoy haciendo algo mal aquí?

Actualización: solo quería señalar: estos registros son duplicados en función de un campo de ID no clave / no indexado enumerado anteriormente. El ID es un campo de texto que, aunque tiene el mismo valor, es un caso diferente al de los otros datos que causan el problema.


Dependiendo de la naturaleza de las filas duplicadas, parece que lo único que desea es tener mayúsculas y minúsculas en esas columnas. Establecer la intercalación en estas columnas debe ser lo que busca:

SELECT DISTINCT p.IDNO COLLATE SQL_Latin1_General_CP1_CI_AS, p.FirstName COLLATE SQL_Latin1_General_CP1_CI_AS, p.LastName COLLATE SQL_Latin1_General_CP1_CI_AS FROM people P

http://msdn.microsoft.com/en-us/library/ms184391.aspx


Después de una cuidadosa consideración, este dillema tiene algunas soluciones diferentes:

Agregar todo Use un agregado en cada columna para obtener el valor de campo más grande o más pequeño. Esto es lo que estoy haciendo ya que se necesitan 2 registros parcialmente llenados y "fusiona" los datos.

http://sqlfiddle.com/#!3/59cde/1

SELECT UPPER(IDNo) AS user_id , MAX(FirstName) AS name_first , MAX(LastName) AS name_last , MAX(entry) AS row_num FROM people P GROUP BY IDNo

Obtener el primer (o último registro)

http://sqlfiddle.com/#!3/59cde/23

-- ------------------------------------------------------ -- Notes -- entry: Auto-Number primary key some sort of unique PK is required for this method -- IDNo: Should be primary key in feed, but is not, we are making an upper case version -- This gets the first entry to get last entry, change MIN() to MAX() -- ------------------------------------------------------ SELECT PC.user_id ,PData.FirstName ,PData.LastName ,PData.entry FROM ( SELECT P2.user_id ,MIN(P2.entry) AS rownum FROM ( SELECT UPPER(P.IDNo) AS user_id , P.entry FROM people P ) AS P2 GROUP BY P2.user_id ) AS PC LEFT JOIN people PData ON PData.entry = PC.rownum ORDER BY PData.entry


Prueba esto

SELECT * FROM people P where P.IDNo in (SELECT DISTINCT IDNo FROM people)


Resulta que lo estaba haciendo mal, necesitaba realizar una selección anidada primero de solo las columnas importantes, y hacer una clara selección de eso para evitar que las columnas de basura de datos ''únicos'' corrompan mis buenos datos. Lo siguiente parece haber resuelto el problema ... pero intentaré con el conjunto de datos completo más adelante.

SELECT DISTINCT P2.* FROM ( SELECT IDNo , FirstName , LastName FROM people P ) P2

Aquí hay algunos datos de reproducción solicitados: http://sqlfiddle.com/#!3/050e0d/3

CREATE TABLE people ( [entry] int , [IDNo] varchar(3) , [FirstName] varchar(5) , [LastName] varchar(7) ); INSERT INTO people (entry,[IDNo], [FirstName], [LastName]) VALUES (1,''uqx'', ''bob'', ''smith''), (2,''abc'', ''john'', ''willis''), (3,''ABC'', ''john'', ''willis''), (4,''aBc'', ''john'', ''willis''), (5,''WTF'', ''jeff'', ''bridges''), (6,''Sss'', ''bill'', ''doe''), (7,''sSs'', ''bill'', ''doe''), (8,''ssS'', ''bill'', ''doe''), (9,''ere'', ''sally'', ''abby''), (10,''wtf'', ''jeff'', ''bridges'') ;


distinct no es una función. Siempre opera en todas las columnas de la lista de selección.

Su problema es un problema típico de "mayor N por grupo" que puede resolverse fácilmente utilizando una función de ventana:

select ... from ( select IDNo, FirstName, LastName, ...., row_number() over (partition by lower(idno) order by firstname) as rn from people ) t where rn = 1;

Usando la cláusula order by , puede seleccionar cuál de los duplicados desea elegir.

Lo anterior se puede usar en una combinación a la izquierda:

select ... from x left join ( select IDNo, FirstName, LastName, ...., row_number() over (partition by lower(idno) order by firstname) as rn from people ) p on p.idno = x=idno and p.rn = 1 where ...