2009-05-29 18 views
8

¿Hay alguna forma de obtener las filas distintas de mayúsculas y minúsculas de esta consulta SQL SAS? ...¿Es posible hacer una DISTINCT insensible a mayúsculas y minúsculas con SAS (PROC SQL)?

SELECT DISTINCT country FROM companies; 

La solución ideal consistiría en una sola consulta.

resultados ahora se ven como:

Australia 
australia 
AUSTRALIA 
Hong Kong 
HONG KONG 

... en cualquiera de las 2 filas distintas realmente se requiere

Uno podría mayúsculas los datos, pero esto cambia innecesariamente los valores de una manera que no se ajusta al propósito de esta consulta.

Respuesta

6

Si tiene alguna clave int primaria (vamos a llamarlo ID), se puede utilizar:

SELECT country FROM companies 
WHERE id = 
(
    SELECT Min(id) FROM companies 
    GROUP BY Upper(country) 
) 
+0

Gracias. Sospecho que este es el mejor enfoque disponible. También me imagino que será difícil escalar a través de varias columnas distintas y miles de filas, pero le daré una oportunidad. Mi consulta de la vida real es algo más elaborada que el ejemplo utilizado para mi pregunta. – Rog

+0

Debe haber algo de heurística en la solución, y creo que debe decidirlo usted mismo explícitamente (por ejemplo, elija la que tenga la ID más baja). Si su problema SQL es "más grande", publique una pregunta más elaborada y deje que el público de SO lo intente ... :) –

+0

¿Puede explicar en su pregunta por qué la solución superior() es menos que óptima? En esta solución, el caso (correcto, superior, inferior, loco, etc.) es completamente arbitrario y se basa en el orden de los datos. ¿Por qué la primera instancia del caso sería más relevante como resultado de la devolución que la instancia de caso superior (país)? –

2

El caso de normalización parece aconsejable: si se producen 'Australia', 'Australia' y 'AUSTRALIA', ¿cuál de las tres le gustaría como la respuesta "con mayúsculas y minúsculas únicas" a su consulta, después de todo? Si está interesado en algunas heurísticas específicas (por ejemplo, cuente cuántas veces ocurren y elija las más populares), seguramente se puede hacer, pero podría ser una gran cantidad de trabajo extra, así que, ¿cuánto vale esa cantidad de dinero para usted? ?

+0

La intención es utilizar una consulta más complicada para mostrar las direcciones de las que puede elegir un usuario, y no importa mucho de cuál se muestre, siempre que no haya muchos duplicados de casos. – Rog

2

Un método no es de SQL (en realidad sólo un solo paso como el paso de datos sólo crea una vista) le BE:


data companies_v /view=companies_v; 
    set companies (keep=country); 
    _upcase_country = upcase(country); 
run; 

proc sort data=companies_v out=companies_distinct_countries (drop=_upcase_country) nodupkey noequals; 
    by _upcase_country; 
run; 
-2

Creo expresiones regulares pueden ayudar con el patrón que desea tener en su cadena de búsqueda.

Para la expresión regular, puede definir una UDF que se puede preparar viendo el tutorial. www.sqlteam.com/article/regular-expressions-in-t-sql

Gracias.

1

Tal vez me falta algo, pero ¿por qué no:

data testZ; 
    input Name $; 
    cards4; 
Bob 
Zach 
Tim 
Eric 
Frank 
ZacH 
BoB 
eric 
;;;; 
run; 

proc sql; 
    create view distinctNames as 
    select distinct Upper(Name) from testz; 
quit; 

Esto crea una vista con sólo nombres distintos como valores de fila.

+0

Esto innecesariamente cambia los valores de una manera que no se ajusta al propósito de esta consulta. En otras palabras, si existe una versión de caso inferior (o propia) no duplicada, eso es lo que debería aparecer en los resultados. – Rog

0

yo estaba pensando a lo largo de las mismas líneas que Zach, pero pensaba que iba a mirar el problema con un ejemplo más elaborado,

proc sql; 
    CREATE TABLE contacts (
     line1 CHAR(30), line2 CHAR(30), pcode CHAR(4) 
    ); 
    * Different versions of the same address - L23 Bass Plaza 2199; 
    INSERT INTO contacts values('LEVEL 23 bass', 'plaza' '2199'); 
    INSERT INTO contacts values('level 23 bass ', ' PLAZA' '2199'); 

    INSERT INTO contacts values('Level 23', 'bass plaza' '2199'); 
    INSERT INTO contacts values('level 23', 'BASS plaza' '2199'); 

    *full address in line 1; 
    INSERT INTO contacts values('Level 23 bass plaza', '' '2199'); 
    INSERT INTO contacts values(' Level 23 BASS plaza ', '' '2199'); 

;quit; 

Ahora podemos hacer salir
i. Uno de cada categoría? Es decir, tres direcciones?
O
ii. ¿O solo una dirección? en caso afirmativo, ¿qué versión deberíamos preferir?

Implementación de caso 1 puede ser tan simple como:

proc sql; 
    SELECT DISTINCT UPCASE(trim(line1)), UPCASE(trim(line2)), pcode 
    FROM contacts 
;quit; 

Implementación de caso 2 puede ser tan simple como:

proc sql; 
    SELECT DISTINCT UPCASE(trim(line1) || ' ' || trim(line2)) , pcode 
    FROM contacts 
;quit; 
+0

En el segundo caso, podríamos usar un * carácter especial * para delimitar las columnas para que podamos separarlas más tarde. es decir. SELECT upcase DISTINCT (trim (línea 1) || '$$' || recortar (line2)) AS dirección, pcode de los contactos ; Así que si podemos tokenizar la dirección de nuevo a line1 y line2 si es necesario ... Solo que estoy seguro de que hay mejores formas de hacerlo ... :) – Raz

+0

Queremos el caso 2 (1 dirección), pero idealmente el El resultado debe ser una de las direcciones existentes, no una nueva versión en mayúsculas. – Rog

0

De SAS 9:

proc ordenar los datos = input_ds SORTSEQ = lingüística (strengh = primaria);

by sort_vars; 

ejecutar;

Cuestiones relacionadas