Rango con varios campos

22/06/2004 - 21:35 por Carlos Gutierrez | Informe spam
Hola

Tengo poca experiencia con consultas complejas, ahorita tengo duda con esto:

Suponiendo una tabla:

CampoA,CampoB
1,6
1,7
1,8
2,6
2,7
2,8
3,6
3,7
3,8

con un indice sobre Campo1,Campo2

¿Como puedo hacer un query que me de el rango de 1,8 a 3,6?, osea:
1,8
2,6
2,7
2,8
3,6
y que ademas este optimizado para usar el indice?

SELECT * FROM Tabla WHERE CampoA BETWEEN 1 and 3 AND CampoB BETWEEN 'c' AND
'a'

no funciona

SELECT * FROM Tabla WHERE ((CampoA*100)+CampoB) BETWEEN 108 AND 306

si funciona, pero hace un Scan, no un Seek.

Segun yo, deberia ser algo asi:

SELECT * FROM Tabla WHERE CampoA,CampoB BETWEEN 1,8 AND 3,6

pero esta sintaxis no existe.

Gracias de antemano por cualquier idea o comentario.

Carlos Gutiérrez
carlosg@sca.com.mx

Gracias de

Preguntas similare

Leer las respuestas

#6 Carlos Gutierrez
24/06/2004 - 21:36 | Informe spam
Javier:

Muchas gracias por la informacion.


"Javier Loria" escribió en el mensaje
news:O0O%
Hola Carlos:
El uso o no de los indices dependera de la densidad y de la cantidad


de
los datos.
En el caso que pusiste, asumamos
/* Creacion de Tabla de Pruebas */
CREATE TABLE Pruebas(
CampoA INT NOT NULL
, CampoB INT NOT NULL
, Relleno CHAR(100) NOT NULL
DEFAULT ('')
)
/* Indice Clustered */
CREATE UNIQUE CLUSTERED INDEX Clust_Pruebas ON Pruebas(CampoA, CampoB)
/* Inserta 100,000 Filas */
INSERT INTO Pruebas(CampoA, CampoB)
SELECT N1.Numero, N2.Numero
FROM Numeros AS N1
CROSS JOIN Numeros AS N2
WHERE N1.Numero<00 AND N2.Numero<0
/* Fin de Codigo */
Agunas notas: Puse un a columna relleno con 100 caracteres para simular
otras columnas, el uso de nulos afecta a los indices, la primera prueba es
con un UNIQUE CLUSTERED INDEX, la tabla de numeros es una tabla de ayuda


que
tiene un monton de numeros consecutivos del 1 en adelante.
Un SELECT del tipo:
=> SELECT CampoA, CampoB
FROM Pruebas
WHERE CampoA BETWEEN 1 AND 8
AND CampoB BETWEEN 3 AND 6
=> Usa perfectamente el indice haciendo un CLUSTERED INDEX SEEK y haciendo
unicamente 13 logical reads, lo cual es bastante eficiente.
Si botamos el indice Clustered y construimos un indice UNIQUE


NONCLUSTERED:
=> DROP INDEX Pruebas.Clust_Pruebas
CREATE UNIQUE NONCLUSTERED INDEX NoClust_Pruebas
ON Pruebas(CampoA, CampoB)
=> En este caso es mas eficiente (ya que tiene un indice cubierto, y no
necesita ir a la tabla), lo resuelve con un Index Seek y 3 logical reads.
Para una tabla con 100,000 filas eso es MUY RAPIDO.
Claro si hubieramos pedido la columna relleno los numeros se hubieran
invertido y el primero hubiera sido mas rapido y el segundo mas lento.
La forma del SELECT que mencionaste:
SELECT...
FROM ...
WHERE ColumnaA BETWEEN ... AND ...
AND ColumnaB BETWEEN ... AND ...
Es una forma que le permite al SQL optimizar el uso de indices con


facilidad
la forma:
SELECT ... FROM ... WHERE ((ColumnaA*100)+ColumnaB) BETWEEN ... and ...
debe evitarse porque no permite usar los indices.
El porque no los usa en tus consultas dependeran principalmente de:
a) cantidad de los datos: Si son muy pocos datos el servidor prefiere
con frecuencia leer los datos directamente de la Tabla (Table Scan) y no


se
complica con los indices.
b) Densidad de los datos: Si los datos estan muy concentrados en 1 o 2
valores los indices no son selectivos y no le ayudan al servidor a buscar
las respuestas correctas, con frecuencia termina leyendo directamente al
Tabla (Tabla Scan)
Espero te sirva,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.
Carlos Gutierrez escribio:
> Hola
>
> Tengo poca experiencia con consultas complejas, ahorita tengo duda
> con esto:
>
> Suponiendo una tabla:
>
> CampoA,CampoB
> 1,6
> 1,7
> 1,8
> 2,6
> 2,7
> 2,8
> 3,6
> 3,7
> 3,8
>
> con un indice sobre Campo1,Campo2
>
> ¿Como puedo hacer un query que me de el rango de 1,8 a 3,6?, osea:
> 1,8
> 2,6
> 2,7
> 2,8
> 3,6
> y que ademas este optimizado para usar el indice?
>
> SELECT * FROM Tabla WHERE CampoA BETWEEN 1 and 3 AND CampoB BETWEEN
> 'c' AND 'a'
>
> no funciona
>
> SELECT * FROM Tabla WHERE ((CampoA*100)+CampoB) BETWEEN 108 AND 306
>
> si funciona, pero hace un Scan, no un Seek.
>
> Segun yo, deberia ser algo asi:
>
> SELECT * FROM Tabla WHERE CampoA,CampoB BETWEEN 1,8 AND 3,6
>
> pero esta sintaxis no existe.
>
> Gracias de antemano por cualquier idea o comentario.


email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida