until - while sql español
SQL Server 2008: TOP 10 y distintos (12)
Creo que el problema es que quieres un resultado para cada p.id?
Pero está obteniendo resultados "duplicados" para algunos p.id, ¿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.
Necesitas algo como
SELECT TOP 10 p.id, max( p1.nm ), max (p1.val), ...
FROM ...
GROUP BY p.id
No necesitará la palabra clave distinct entonces.
Como dice el título, estoy usando SQL Server 2008. Disculpas si esta pregunta es muy básica. Solo he estado usando SQL por unos días. En este momento tengo la siguiente consulta:
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 seleccionar top n junto con distintos valores en la columna de id. La búsqueda en algunos foros dice usar
SELECT DISTINCT TOP 10 ...
pero cuando reemplazo la primera línea con
SELECT DISTINCT TOP 10 p.id, pl.nm, pl.val, pl.txt_val
Obtengo los mismos resultados que sin la palabra distinct. ¿Qué debería estar haciendo solo para filtrar entradas de identificación duplicadas?
Gracias.
Esta es la respuesta correcta y puedes encontrar 3 alturas de 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
La opción fácil es usar agrupar por y seleccionar min / max 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 ser bastante tedioso para la tabla ancha, por lo que la otra opción es usar el rango sobre y la partición.
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
Pocas ideas:
- Usted tiene bastantes campos en su declaración seleccionada. Cualquier valor que sea diferente de otro hará que esa fila sea distinta.
- 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 ordenar utilizando DONDE
- Es completamente posible obtener los mismos resultados aunque utilice TOP y DISTINCT y WHERE. Verifique para asegurarse de que los datos que está consultando efectivamente puedan filtrarse y ordenarse de la manera que espera.
Pruebe 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
Tenga en cuenta que comenté algunos de los SELECT para limitar su conjunto de resultados y la lógica DISTINCT.
Puede usar una Expresión de tabla común para obtener los 10 primeros identificadores distintos y luego unirlos 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é te unes a la tabla de "pacientes", si nunca seleccionas ningún campo de ella?
Sé que este hilo es viejo, pero pensé que arrojaría lo que surgió ya que me encontré con este 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)
Tratar
SELECT distinct TOP 10 MyId FROM sometable
bueno, yo no lo hubiera esperado, pero SELECT de Halim distinto TOP 10 MyId FROMtable
es funcionalmente idéntico a la selección superior 10 p.id de Vaishnavi Kumar de (seleccione distinct p.id from tablename) tablename
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 selects:
name
1 bob
2 jim
3 john
4 luke
5 mark
es curioso que seleccionar los 5 principales distintos no sea válido, pero seleccione los 5 principales distintos y funcione como podría esperar para seleccionar 5 principales distintos para que funcionen.
DISTINCT
elimina las filas si todos los valores seleccionados son iguales. Aparentemente, tiene entradas con el mismo p.id
pero con diferentes pl.nm
(o pl.val
o pl.txt_val
). La respuesta a su pregunta depende de cuál de estos valores quiera mostrar en una fila con su p.id
(¿el primero? ¿El más pequeño? ¿ p.id
?).
SELECT TOP 14 A, B, C
FROM MyDatabase
Where EXISTS
(
Select Distinct[A] FROM MyDatabase
)
select top 10 * from
(
select distinct p.id, ....
)
trabajará.
select top 10 p.id from(select distinct p.id from tablename)tablename