2010-04-19 8 views
5

no adyacentes Teniendo en cuenta estos datos en SQL Server 2005:SQL Tricky - seleccionar números

SectionID Name 
1   Dan 
2   Dan 
4   Dan 
5   Dan 
2   Tom 
7   Tom 
9   Tom 
10  Tom 

¿Cómo puedo seleccionar registros en los que debe ser sectionid + -2 o más de otra sección del mismo nombre.

El resultado sería:

1 Dan 
4 Dan 
2 Tom 
7 Tom 
9 Tom 

Gracias por leer!

+2

Hmm, dices "1 Dan" está en los resultados y por lo tanto "2 Dan" no es, pero ¿por qué no es que "2 Dan" está en los resultados y por lo tanto "1 Dan" no? Creo que asumes algún orden aquí, que SQL realmente no hace. ¿Qué es lo que realmente quieres lograr? – wilth

+0

@wilth, SQL puede reconocer operadores relacionales como Unreason

+0

@Daniel, ¿qué le devolverías si también tuvieras (3, Dan) en la mesa de salida? ¿Devolverías registros (1, Dan) y (3, Dan) o solo el primero? ¿Es la única condición realmente que la diferencia entre los identificadores seleccionados debe ser mayor que 1 (o hay condiciones adicionales)? Si esa es la única condición, ¿qué desea hacer en caso de secuencia como: 5, 6, 7, 8, 10, 11, 12? (tiene dos soluciones, una que comienza con 5 tiene 4 elementos en la respuesta, pero si comienza con 6 puede seleccionar 5 elementos); cómo distinguir? – Unreason

Respuesta

3
SELECT * 
FROM mytable a 
WHERE NOT EXISTS 
    (SELECT * 
    FROM mytable b 
    WHERE a.Name = b.Name 
    AND a.SectionID = b.SectionID + 1) 
+0

+1 Solución directa y correcta. Un índice compuesto en '(SectionID, Name)' será muy beneficioso para esta consulta. – Tomalak

+1

así que si tuviera datos: '1 Tom 2 Tom 3 Tom 4 Tom' usted obtendría cero registros. Lo cual sospecho que no es correcto. – ninesided

+0

@ninesided, no realmente - la consulta devuelve todos los registros de la tabla a donde para el sectionid no hay registro en la misma tabla con sectionid que es menos por uno (entonces en su contador ejemplo 1 Tom sería devuelto). – Unreason

0

Aquí es LEFT JOIN variante de la respuesta de Anthony (elimina del consecutivas de identificación de los resultados)

SELECT a.* 
FROM mytable a 
    LEFT JOIN mytable b ON a.Name = b.Name AND a.SectionID = b.SectionID + 1 
WHERE b.SectionID IS NULL 

EDIT: Ya existe otra interpretación de la pregunta (simplemente conseguir resultados en la identificación de más de 1 serie Aparte) aquí es otro intento de respuesta:

WITH alternate AS (
SELECT sectionid, 
     name, 
     EXISTS(SELECT a.sectionid 
       FROM mytable b 
       WHERE a.name = b.name AND 
        (a.sectionid = b.sectionid-1 or a.sectionid = b.sectionid+1)) as has_neighbour, 
     row_number() OVER (PARTITION by a.name ORDER BY a.name, a.sectionid) as row_no 
FROM mytable a 
) 
SELECT sectionid, name 
FROM alternate 
WHERE row_no % 2 = 1 OR NOT(has_neighbour) 
ORDER BY name, sectionid; 

da:

sectionid | name 
-----------+------ 
     1 | Dan 
     4 | Dan 
     2 | Tom 
     7 | Tom 
     9 | Tom 

Lógica: si un registro tiene vecinos con el mismo nombre y la identificación +/- 1, se toma cada fila impar, si no tiene tales vecinos, entonces obtiene la fila, independientemente de si es par o impar.

Como se indica en el comentario, la condición es ambigua: al comienzo de cada nueva secuencia, puede comenzar con filas impares o pares y los criterios se seguirán cumpliendo con diferentes resultados (incluso con diferentes resultados).

+0

Diferente, pero todavía tiene el mismo problema que @ninesided mencionado. – PaulG

+0

Mala idea ya que el servidor SQL no podrá convertir esto en un enlace. – erikkallen

+0

@PaulG, ¿puedes explicar el problema? Pedí más detalles sobre un comentario ninesided bajo la respuesta de Anthony, pero ninguno fue proporcionado (por lo que puedo ver ambas consultas devuelven los datos solicitados) @erikkallen, estoy de acuerdo en que no, pero el rendimiento debe ser probado, NO EXISTE de el rendimiento de la subconsulta correlacionada no es obviamente superior al rendimiento LEFT JOIN, incluso con tal alta selectividad. – Unreason