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

#1 Gustavo Larriera [MVP SQL]
22/06/2004 - 21:52 | Informe spam
Sin dudar que es un acertijo interesante el que planteas.

Pregunto: Qué representan esos números? porque veo que intentas usarlos como
si fueran un unico dato (parejas de numeros) por tanto me surge la duda de
diseño... esos números no podrían estar juntos en una sola columna?

La consulta que te ha funcionado no pudo optimizarse debido a que estás
usando una expresión numérica...

Gustavo Larriera, MVP-SQL, MCSE
Uruguay LatAm
Este mensaje se proporciona "COMO ESTA" sin garantias y no otorga ningun
derecho / This posting is provided "AS IS" with no warranties, and confers
no rights.
"Carlos Gutierrez" wrote in message
news:VR%Bc.17974788$
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


Gracias de


Respuesta Responder a este mensaje
#2 Carlos Gutierrez
22/06/2004 - 23:20 | Informe spam
Gustavo:

Gracias por tu respuesta.

Pregunto: Qué representan esos números? porque veo que intentas usarlos
como si fueran un unico dato (parejas de numeros) por tanto me surge la
duda de diseño... esos números no podrían estar juntos en una sola


columna?

Son dos casos en que se me ha presentado esta necesidad:

- Un sistema que conserva información estadistica corporativa mensual, en
este caso el primer campo es el Año y el segundo el Mes, y se necesita sacar
información de periodos que abarcan varios años.
- Un sistema de contabilidad, el primer campo es el numero de cuenta de
mayor y el segundo el de sub-cuenta, se necesita poder imprimir/procesar un
rango arbitrario de cuentas que puede abarcar mas de una cuenta de mayor.

Definitivamente si los dos datos estuvieran en una sola columna no habria
mayor dificultad, pero son estructuras que ya existen. Al parecer estas
estructuras fueron convertidas de un diseño con archivos tipo ISAM en DOS.

Carlos Gutiérrez

Respuesta Responder a este mensaje
#3 Liliana Sorrentino
23/06/2004 - 15:45 | Informe spam
Hola Carlos,
Lo que te propongo hace un Index Seek, bueno, tres en realidad. Según el
plan de ejecución el costo es menor que el Scan de la consulta que tiene la
suma de las columnas.
Tendrías que probar con información real para ver los tiempos y performance.
Saludos... Liliana.

SELECT * FROM #Tabla WHERE CampoA = 1 AND CampoB >= 8
UNION
SELECT * FROM #Tabla WHERE CampoA > 1 AND CampoA < 3
UNION
SELECT * FROM #Tabla WHERE CampoA = 3 AND CampoB <= 6

"Carlos Gutierrez" escribió en el mensaje
news:Yo1Cc.18073084$
Gustavo:

Gracias por tu respuesta.

> Pregunto: Qué representan esos números? porque veo que intentas usarlos
> como si fueran un unico dato (parejas de numeros) por tanto me surge la
> duda de diseño... esos números no podrían estar juntos en una sola
columna?

Son dos casos en que se me ha presentado esta necesidad:

- Un sistema que conserva información estadistica corporativa mensual, en
este caso el primer campo es el Año y el segundo el Mes, y se necesita


sacar
información de periodos que abarcan varios años.
- Un sistema de contabilidad, el primer campo es el numero de cuenta de
mayor y el segundo el de sub-cuenta, se necesita poder imprimir/procesar


un
rango arbitrario de cuentas que puede abarcar mas de una cuenta de mayor.

Definitivamente si los dos datos estuvieran en una sola columna no habria
mayor dificultad, pero son estructuras que ya existen. Al parecer estas
estructuras fueron convertidas de un diseño con archivos tipo ISAM en DOS.

Carlos Gutiérrez



Respuesta Responder a este mensaje
#4 Javier Loria
23/06/2004 - 16:35 | Informe spam
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.
Respuesta Responder a este mensaje
#5 Carlos Gutierrez
24/06/2004 - 21:36 | Informe spam
Liliana,

Interesante idea, voy a hacer pruebas.

Muchisimas gracias.

Carlos Gutiérrez



"Liliana Sorrentino" escribió en el mensaje
news:
Hola Carlos,
Lo que te propongo hace un Index Seek, bueno, tres en realidad. Según el
plan de ejecución el costo es menor que el Scan de la consulta que tiene


la
suma de las columnas.
Tendrías que probar con información real para ver los tiempos y


performance.
Saludos... Liliana.

SELECT * FROM #Tabla WHERE CampoA = 1 AND CampoB >= 8
UNION
SELECT * FROM #Tabla WHERE CampoA > 1 AND CampoA < 3
UNION
SELECT * FROM #Tabla WHERE CampoA = 3 AND CampoB <= 6

"Carlos Gutierrez" escribió en el mensaje
news:Yo1Cc.18073084$
> Gustavo:
>
> Gracias por tu respuesta.
>
> > Pregunto: Qué representan esos números? porque veo que intentas


usarlos
> > como si fueran un unico dato (parejas de numeros) por tanto me surge


la
> > duda de diseño... esos números no podrían estar juntos en una sola
> columna?
>
> Son dos casos en que se me ha presentado esta necesidad:
>
> - Un sistema que conserva información estadistica corporativa mensual,


en
> este caso el primer campo es el Año y el segundo el Mes, y se necesita
sacar
> información de periodos que abarcan varios años.
> - Un sistema de contabilidad, el primer campo es el numero de cuenta de
> mayor y el segundo el de sub-cuenta, se necesita poder imprimir/procesar
un
> rango arbitrario de cuentas que puede abarcar mas de una cuenta de


mayor.
>
> Definitivamente si los dos datos estuvieran en una sola columna no


habria
> mayor dificultad, pero son estructuras que ya existen. Al parecer estas
> estructuras fueron convertidas de un diseño con archivos tipo ISAM en


DOS.
>
> Carlos Gutiérrez
>
>
>


Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida