2009-12-17 22 views
32

Como dice el título, estoy usando SQL Server 2008. Disculpe si esta pregunta es muy básica. Solo he estado usando SQL por unos días. Ahora mismo tengo la siguiente consulta:SQL Server 2008: TOP 10 y distinto

SELECT TOP 10 p.id, pl.nm, pl.val, pl.txt_val 

from dm.labs pl 
join mas_data.patients p  
    on pl.id = p.id 
    where pl.nm like '%LDL%' 
    and val is not null 

Lo que quiero hacer es usar select subir n junto con los valores distintos en la columna id. Buscando a través de algunos foros dice que use

SELECT DISTINCT TOP 10 ... 

pero cuando se sustituye la primera línea con

SELECT DISTINCT TOP 10 p.id, pl.nm, pl.val, pl.txt_val 

me da los mismos resultados que sin la palabra distinta. ¿Qué debería estar haciendo solo para filtrar entradas de identificación duplicadas?

Gracias.

+1

Creo que necesita expresar su pregunta de manera más explícita. Si tiene tres filas con p.id = 1, ¿qué fila quiere? ¿El que tiene el pl.nm más alto o más bajo, pl.val, pl.txt_val, alguna combinación o algo completamente diferente? SQL no puede aplicar DISTINCT() de esta manera, pero hay formas de obtener una fila por p.id. Solo necesita definir los requisitos, y podemos ayudar ... –

+0

¿ID de paciente es una clave primaria? – dan

Respuesta

9

La opción más fácil es usar GROUP BY y seleccione mínimo/máximo para todos los demás campos

SELECT TOP 10 
    p.id, 
    max(pl.nm), 
    max(pl.val), 
    max(pl.txt_val) 
from 
    dm.labs pl 
join 
    mas_data.patients p  
on 
    pl.id = p.id 
    where 
    pl.nm like '%LDL%' 
and 
    val is not null 
group by 
    p.id 

Esto puede llegar a ser muy tedioso para la tabla ancha que la otra opción es utilizar rango sobre y partiion

SELECT TOP 10 
    p.id, 
    pl.nm, 
    pl.val, 
    pl.txt_val, 
    rank() over(partition by p.id order by p.id) as Rank 
from 
    dm.labs pl 
join 
    mas_data.patients p  
on 
    pl.id = p.id 
    where 
    pl.nm like '%LDL%' 
and 
    val is not null 
and 
    Rank = 1 
+3

No creo que esto esté permitido. No puede hacer referencia a columnas creadas en la lista SELECT en la cláusula WHERE. – siride

+1

Echa un vistazo a esta respuesta de Halim justo debajo: https://stackoverflow.com/a/37642799/4212710 – typoerrpr

+0

'La opción fácil' – eddyP23

1
select top 10 * from 
(
    select distinct p.id, .... 
) 

funcionará.

+0

él quiere valores distintos para los identificadores hasta donde yo pueda ver, así que esto no funcionará –

0

DISTINCT elimina filas si todos los valores seleccionados son iguales. Aparentemente, tiene entradas con el mismo p.id pero con diferente pl.nm (o pl.val o pl.txt_val). La respuesta a su pregunta depende de cuál de estos valores desea mostrar en la fila one con su p.id (la primera? La más pequeña? Alguna?).

4

algunas ideas:

  1. Usted tiene un buen número de campos de la instrucción de selección. Cualquier valor que sea diferente de otro hará que esa fila sea distinta.
  2. Las cláusulas TOP generalmente se combinan con las cláusulas WHERE. De lo contrario, TOP no significa mucho. ¿Top de qué? La forma de especificar "arriba de qué" es para ordenar utilizando DONDE
  3. Es posible obtener los mismos resultados aunque utilice TOP, DISTINCT y WHERE. Verifique para asegurarse de que los datos que está consultando efectivamente puedan filtrarse y ordenarse de la manera que espera.

intentar algo como esto:

SELECT DISTINCT TOP 10 p.id, pl.nm -- , pl.val, pl.txt_val 
FROM dm.labs pl 
JOIN mas_data.patients p  
on pl.id = p.id 
where pl.nm like '%LDL%' 
and val is not null 
ORDER BY pl.nm 

en cuenta que he comentado algunos de los SELECT para limitar el conjunto de resultados y lógica distinta.

0

Creo que el problema es que quiere un resultado para cada p.id?

Pero está obteniendo resultados "duplicados" para algunos p.id, ¿no es así?

La palabra clave DISTINCT se aplica a todo el conjunto de resultados, por lo que se aplica a pl.nm, pl.val, pl.txt_val, no solo p.id.

Usted necesita algo así como

SELECT TOP 10 p.id, max(p1.nm), max (p1.val), ... 
FROM ... 
GROUP BY p.id 

no se necesita la palabra clave distinta a continuación.

+0

-1 El uso de MAX de esta manera hará que el resultado sea arbitrario. –

+0

sí, pero si quiere un resultado por p.id, tendrá que hacer algo arbitrario o dejar esas columnas por completo – MikeW

+1

No necesariamente, si desea la fila que está asociada con una fila específica para cada p.id, por ejemplo, el que tiene max (nm) o max(), quiere que toda la fila, no valores máximos aleatorios de filas potencialmente diferentes. La solución que dio Paul Creasey tiene el potencial de hacer esto simplemente cambiando el orden dentro de la cláusula over(). No estoy seguro de qué cobarde votó negativamente su respuesta sin indicar su (s) razón (es). –

0

Se podría utilizar una expresión de tabla común para obtener los 10 mejores de distintos ID y luego unirse a las dirigidas al resto de sus datos:

;WITH TopTenIDs AS 
( 
    SELECT DISTINCT TOP 10 id 
    FROM dm.labs 
    ORDER BY ...... 
) 
SELECT 
    tti.id, pl.nm, pl.val, pl.txt_val 
FROM 
    TopTenIDs tti 
INNER JOIN 
    dm.labs pl ON pl.id = tti.id 
INNER JOIN 
    mas_data.patients p ON pl.id = p.id 
WHERE 
    pl.nm like '%LDL%' 
    AND val IS NOT NULL 

Eso debería funcionar. Eso sí: si tienes una cláusula "TOP x", normalmente también necesitas una cláusula ORDER BY; si quieres TOP 10, debes decirle al sistema en qué orden está "TOP".

PD: ¿por qué incluso te unes a la tabla de "pacientes", si nunca seleccionas ningún campo de ella?

2

Sé que este hilo es antiguo, pero pensé que arrojaría lo que surgió ya que me encontré con el mismo problema. Puede que no sea eficiente, pero creo que hace el trabajo bien.

SELECT TOP 10 p.id, pl.nm, pl.val, pl.txt_val 
INTO #yourTempTable 
from dm.labs pl 
join mas_data.patients p on pl.id = p.id 
where pl.nm like '%LDL%' and val is not null 

select p.id, pl.nm, pl.val, pl.txt_val 
from #yourTempTable 
where id IN (select distinct id from #yourTempTable) 
0
SELECT TOP 14 A, B, C 
    FROM MyDatabase 
    Where EXISTS 
    (
    Select Distinct[A] FROM MyDatabase 
    ) 
24
select top 10 p.id from(select distinct p.id from tablename)tablename 
+0

simple y elegante. Debería ser la respuesta más votado. –

+0

No creo que esto funcione, ya que los ID de las distintas órdenes ascienden –

0

Esta es la respuesta correcta y se puede encontrar 3 alturas valor de la tabla

SELECT TOP(1) T.id FROM (SELECT DISTINCT TOP(3) st.id FROM Table1 AS t1 , Table2 AS t2 WHERE t1.id=t2.id ORDER BY (t2.id) DESC) T ORDER BY(T.id) ASC 
67

Try

SELECT distinct TOP 10 MyId FROM sometable 
+7

Esta es la respuesta correcta – Hans

+0

Esto también funciona en Sybase 12 –

+0

. Solo tuve que cambiarlos. Muy agradable. –

1

bien que no lo hubiera esperado , pero el de Halim SELECCIONA el TOP 10 MyId de algunos tabla

es funcionalmente idéntico a Vaishnavi Kumar de seleccionar 10 p.id superior de (seleccione distinta p.id de nombretabla) nombredetabla

create table #names ([name] varchar(10)) 
insert into #names ([name]) values ('jim') 
insert into #names ([name]) values ('jim') 
insert into #names ([name]) values ('bob') 
insert into #names ([name]) values ('mary') 
insert into #names ([name]) values ('bob') 
insert into #names ([name]) values ('mary') 
insert into #names ([name]) values ('john') 
insert into #names ([name]) values ('mark') 
insert into #names ([name]) values ('matthew') 
insert into #names ([name]) values ('luke') 
insert into #names ([name]) values ('peter') 

select distinct top 5 [name] from #names 

select top 5 * from (select distinct [name] from #names) subquery 

drop table #names 

produce los mismos resultados para ambos selecciona:

name 
1 bob 
2 jim 
3 john 
4 luke 
5 mark 

es curioso que selecciones los 5 principales distintos no es válido, pero seleccione los 5 principales distintos y funcione como podría esperar seleccione los 5 principales distintos para que funcionen.