ayuda de algun experto en transact sql

16/08/2007 - 15:36 por Guillermo Villanueva | Informe spam
Buenas tardes, necesito desarrollar una función en mi base de datos.
Resulta que tengo códigos numéricos que teóricamente son secuenciales (NO
SON DE TIPO IDENTITY). pero en algunos casos se eliminan ciertos rangos
entonces me quedan cosas como:
fp_codigo
1
2
3
4
7
8
9
18
19
20
21
22
42
43
Necesito una función BuscarRango(x,desde,hasta) que me diga si es que hay
algún rango disponible de x o mas lugares, entonces la función me devolvería
verdadero si es que si hay y falso si no hay, y en caso de que sea verdadero
debería darme en desde, hasta el rango disponible, ejemplo
BuscarRango(1000,desde,hasta) --> falso
BuscarRango(5,desde,hasta) --> verdadero 10 17

Se como hacerlo en powerbuilder pero no tengo la menor idea de como hacerlo
en transact lo cual sería mucho mejor. Desde ya muchas gracias.

Guillermo

Preguntas similare

Leer las respuestas

#6 Danilo Reinoso
16/08/2007 - 22:18 | Informe spam
Saludos.

Puede probar algo como esto.
Tabla prueba seria tu tabla.


DECLARE @MyInicio int, @MyFinal int, @MyContador int
SET @MyInicio = 1001
SET @MyFinal = (SELECT MAX(NUMERO) FROM PRUEBA)
SET @MyContador = @MyInicio
CREATE TABLE #LOSTSEQUENCE (MyID int)
WHILE @MyContador < @MyFinal
BEGIN
IF NOT EXISTS (SELECT Numero FROM Prueba WHERE Numero = @MyContador)
INSERT INTO #LOSTSEQUENCE VALUES(@MyContador)
SET @MyContador = @MyContador+1
CONTINUE
END
/*SELECT 'Series perdidas:'*/
SELECT MyID FROM #LOSTSEQUENCE

"Guillermo Villanueva" wrote in message
news:OlZet%
Me respondo solo:
lo puedo hacer con una consulta de la siguiente manera:
select A.fp_codigo, MIN(B.fp_codigo )
from FacturasPad A inner join FacturasPad B
on A.fp_codigo < B.fp_codigo

GROUP BY A.fp_codigo
HAVING MIN(B.fp_codigo) - A.fp_codigo > 7

El problema es que es bastante lento para devolverme el resultado, no
importa.

"Guillermo Villanueva" escribió en el
mensaje news:%23%
Buenas tardes, necesito desarrollar una función en mi base de datos.
Resulta que tengo códigos numéricos que teóricamente son secuenciales (NO
SON DE TIPO IDENTITY). pero en algunos casos se eliminan ciertos rangos
entonces me quedan cosas como:
fp_codigo
1
2
3
4
7
8
9
18
19
20
21
22
42
43
Necesito una función BuscarRango(x,desde,hasta) que me diga si es que hay
algún rango disponible de x o mas lugares, entonces la función me
devolvería verdadero si es que si hay y falso si no hay, y en caso de que
sea verdadero debería darme en desde, hasta el rango disponible, ejemplo
BuscarRango(1000,desde,hasta) --> falso
BuscarRango(5,desde,hasta) --> verdadero 10 17

Se como hacerlo en powerbuilder pero no tengo la menor idea de como
hacerlo en transact lo cual sería mucho mejor. Desde ya muchas gracias.

Guillermo





Respuesta Responder a este mensaje
#7 Guillermo Villanueva
17/08/2007 - 16:36 | Informe spam
Es un buen recurso para obtener las series perdidas, aprovecho para
consultar, hace muchos años que trabajo con bases de datos y nunca nunca
utilicé este tipo de tablas temporales
Tiene buena performance el trabajo con estas?
Se borran solas depues de ejecutar el script? o debo borrarlas?
Se les puede declarar claves primarias, restricciones y dependencias?

"Danilo Reinoso" escribió en el mensaje
news:%
Saludos.

Puede probar algo como esto.
Tabla prueba seria tu tabla.


DECLARE @MyInicio int, @MyFinal int, @MyContador int
SET @MyInicio = 1001
SET @MyFinal = (SELECT MAX(NUMERO) FROM PRUEBA)
SET @MyContador = @MyInicio
CREATE TABLE #LOSTSEQUENCE (MyID int)
WHILE @MyContador < @MyFinal
BEGIN
IF NOT EXISTS (SELECT Numero FROM Prueba WHERE Numero = @MyContador)
INSERT INTO #LOSTSEQUENCE VALUES(@MyContador)
SET @MyContador = @MyContador+1
CONTINUE
END
/*SELECT 'Series perdidas:'*/
SELECT MyID FROM #LOSTSEQUENCE

"Guillermo Villanueva" wrote in
message news:OlZet%
Me respondo solo:
lo puedo hacer con una consulta de la siguiente manera:
select A.fp_codigo, MIN(B.fp_codigo )
from FacturasPad A inner join FacturasPad B
on A.fp_codigo < B.fp_codigo

GROUP BY A.fp_codigo
HAVING MIN(B.fp_codigo) - A.fp_codigo > 7

El problema es que es bastante lento para devolverme el resultado, no
importa.

"Guillermo Villanueva" escribió en
el mensaje news:%23%
Buenas tardes, necesito desarrollar una función en mi base de datos.
Resulta que tengo códigos numéricos que teóricamente son secuenciales
(NO SON DE TIPO IDENTITY). pero en algunos casos se eliminan ciertos
rangos entonces me quedan cosas como:
fp_codigo
1
2
3
4
7
8
9
18
19
20
21
22
42
43
Necesito una función BuscarRango(x,desde,hasta) que me diga si es que
hay algún rango disponible de x o mas lugares, entonces la función me
devolvería verdadero si es que si hay y falso si no hay, y en caso de
que sea verdadero debería darme en desde, hasta el rango disponible,
ejemplo
BuscarRango(1000,desde,hasta) --> falso
BuscarRango(5,desde,hasta) --> verdadero 10 17

Se como hacerlo en powerbuilder pero no tengo la menor idea de como
hacerlo en transact lo cual sería mucho mejor. Desde ya muchas gracias.

Guillermo









Respuesta Responder a este mensaje
#8 Danilo Reinoso
17/08/2007 - 20:37 | Informe spam
En general hay que tratar de evitar las tablas temporales en SQL. Los BOL
libro en linea dice que se use variable tipo table en lugar de tablas
temporales.

Sacado de los BOL.
Cuando se crean tablas temporales globales o locales, la sintaxis CREATE
TABLE admite la definición de restricciones, excepto las restricciones
FOREIGN KEY. Si en una tabla temporal se especifica una restricción FOREIGN
KEY, la instrucción devuelve un mensaje de advertencia que indica que la
restricción se saltó y que la tabla se ha creado sin las restricciones
FOREIGN KEY. En las restricciones FOREIGN KEY no se puede hacer referencia a
tablas temporales.

Considere la posibilidad de utilizar variables de tabla en lugar de tablas
temporales. Las tablas temporales son útiles cuando es necesario crear en
ellas índices de forma explícita, o bien cuando los valores de tabla deben
ser visibles en varios procedimientos almacenados o funciones. En general,
las variables de tabla contribuyen a que el procesamiento de las consultas
sea más eficaz. Para obtener más información, consulte table.



"Guillermo Villanueva" wrote in message
news:
Es un buen recurso para obtener las series perdidas, aprovecho para
consultar, hace muchos años que trabajo con bases de datos y nunca nunca
utilicé este tipo de tablas temporales
Tiene buena performance el trabajo con estas?
Se borran solas depues de ejecutar el script? o debo borrarlas?
Se les puede declarar claves primarias, restricciones y dependencias?

"Danilo Reinoso" escribió en el
mensaje news:%
Saludos.

Puede probar algo como esto.
Tabla prueba seria tu tabla.


DECLARE @MyInicio int, @MyFinal int, @MyContador int
SET @MyInicio = 1001
SET @MyFinal = (SELECT MAX(NUMERO) FROM PRUEBA)
SET @MyContador = @MyInicio
CREATE TABLE #LOSTSEQUENCE (MyID int)
WHILE @MyContador < @MyFinal
BEGIN
IF NOT EXISTS (SELECT Numero FROM Prueba WHERE Numero = @MyContador)
INSERT INTO #LOSTSEQUENCE VALUES(@MyContador)
SET @MyContador = @MyContador+1
CONTINUE
END
/*SELECT 'Series perdidas:'*/
SELECT MyID FROM #LOSTSEQUENCE

"Guillermo Villanueva" wrote in
message news:OlZet%
Me respondo solo:
lo puedo hacer con una consulta de la siguiente manera:
select A.fp_codigo, MIN(B.fp_codigo )
from FacturasPad A inner join FacturasPad B
on A.fp_codigo < B.fp_codigo

GROUP BY A.fp_codigo
HAVING MIN(B.fp_codigo) - A.fp_codigo > 7

El problema es que es bastante lento para devolverme el resultado, no
importa.

"Guillermo Villanueva" escribió en
el mensaje news:%23%
Buenas tardes, necesito desarrollar una función en mi base de datos.
Resulta que tengo códigos numéricos que teóricamente son secuenciales
(NO SON DE TIPO IDENTITY). pero en algunos casos se eliminan ciertos
rangos entonces me quedan cosas como:
fp_codigo
1
2
3
4
7
8
9
18
19
20
21
22
42
43
Necesito una función BuscarRango(x,desde,hasta) que me diga si es que
hay algún rango disponible de x o mas lugares, entonces la función me
devolvería verdadero si es que si hay y falso si no hay, y en caso de
que sea verdadero debería darme en desde, hasta el rango disponible,
ejemplo
BuscarRango(1000,desde,hasta) --> falso
BuscarRango(5,desde,hasta) --> verdadero 10 17

Se como hacerlo en powerbuilder pero no tengo la menor idea de como
hacerlo en transact lo cual sería mucho mejor. Desde ya muchas gracias.

Guillermo













Respuesta Responder a este mensaje
#9 Miguel Egea
28/08/2007 - 13:28 | Informe spam
Yo como muchos sabéis soy de la brigada anticursores, si el cursor además
está mezclado con una tabla temporal pues aún peor, aunque el caso no
tenga mayor importancia si una vez probado no te mata el rendimiento de tu
server. Aquí os pongo un ejemplo. La consulta propuesta por Danilo, hace
casi 28000 lecturas, según dice profiler, la que yo propongo, sigue haciendo
demasiadas pero para este ejemplo cuando se buscan huecos de 1 elemento
(hay formas más eficaces para esto) hace 179 lecturas, cuando se buscan
huecos de 3 elementos hace 704 lecturas. Cuando buscamos huecos de 4 no
encuentra y hace el máximo de lecturas 10537. Si se van a buscar huecos más
grandes habría que ver si es eficaz, es posible que no.

Aún así me parece interesante el procedimiento para ver la potencia de
T-SQL. Luego intentaré publicarlo en el blog y en portalsql con una
explicación detallada.

create table pruebas (id int identity(1,1) not null primary key,
foo char(6000) default '')
go
declare @i int
set @i=0
while @i<10000
begin
begin tran

insert into pruebas default values

if substring(cast(rand() as varchar(100)),3,1)='9'
rollback
else
commit
set @i=@i+1
end
go
set statistics io on

go
select id from pruebas
go
create index ix_id on pruebas (id)
go
select id from pruebas
go
drop index pruebas.ix_id
go
DECLARE @MyInicio int, @MyFinal int, @MyContador int
SET @MyInicio = 1001
SET @MyFinal = (SELECT MAX(id) FROM PRUEBAs)
SET @MyContador = @MyInicio
CREATE TABLE #LOSTSEQUENCE (MyID int)
WHILE @MyContador < @MyFinal
BEGIN
IF NOT EXISTS (SELECT id FROM Pruebas WHERE id= @MyContador)
INSERT INTO #LOSTSEQUENCE VALUES(@MyContador)
SET @MyContador = @MyContador+1
CONTINUE
END
/*SELECT 'Series perdidas:'*/
SELECT MyID FROM #LOSTSEQUENCE
go
create index ix_id on pruebas (id)
go
go
para muchas cosas
with mycte(id)
as
(
select 1 id
union all
select id+1 from mycte where id<100000
)
select id into nums from mycte option (maxrecursion 0);

go
alter proc BuscarRangoLibre @posiciones int, @desde int output,@hasta int
output
as
begin

with myCte(cont) as
(select 1 cont
union all
select cont+1 from myCte where cont<@posiciones)
select cont into #t from mycte;


select top 1 row,inicio+1
from (
select d.row,d.id inicio,d.id+cont valor
from (
select p.id, row_number() over (order by p.id) row
from pruebas p left join pruebas p2 on p.id+1=p2.id
where p2.id is null) d
cross join #t
) der left join pruebas on der.valor=pruebas.id
group by row,inicio
having count(id)=0;
drop table #t;

end
go
@desde int, @hasta int
exec BuscarRangoLibre 3,@desde output,@hasta output

"Danilo Reinoso" wrote in message
news:%
En general hay que tratar de evitar las tablas temporales en SQL. Los BOL
libro en linea dice que se use variable tipo table en lugar de tablas
temporales.

Sacado de los BOL.
Cuando se crean tablas temporales globales o locales, la sintaxis CREATE
TABLE admite la definición de restricciones, excepto las restricciones
FOREIGN KEY. Si en una tabla temporal se especifica una restricción
FOREIGN KEY, la instrucción devuelve un mensaje de advertencia que indica
que la restricción se saltó y que la tabla se ha creado sin las
restricciones FOREIGN KEY. En las restricciones FOREIGN KEY no se puede
hacer referencia a tablas temporales.

Considere la posibilidad de utilizar variables de tabla en lugar de tablas
temporales. Las tablas temporales son útiles cuando es necesario crear en
ellas índices de forma explícita, o bien cuando los valores de tabla deben
ser visibles en varios procedimientos almacenados o funciones. En general,
las variables de tabla contribuyen a que el procesamiento de las consultas
sea más eficaz. Para obtener más información, consulte table.



"Guillermo Villanueva" wrote in
message news:
Es un buen recurso para obtener las series perdidas, aprovecho para
consultar, hace muchos años que trabajo con bases de datos y nunca nunca
utilicé este tipo de tablas temporales
Tiene buena performance el trabajo con estas?
Se borran solas depues de ejecutar el script? o debo borrarlas?
Se les puede declarar claves primarias, restricciones y dependencias?

"Danilo Reinoso" escribió en el
mensaje news:%
Saludos.






Yo, como muchos sabéis soy de la brigada anticursores ;-). Un cursor y una
tabla temporal juntos, aún más peligroso en mi opinión. De todas formas como
siempre todo depende. a mi me gusta pensar en forma de conjuntos así que
aquí va mi solución. Disculpad que haya tardado tanto, pero es que esto me
pilló en vacaciones, (y en vacaciones debo haber matados 2000 millones de
neuronas -1 millón por cada cerveza-).





Puede probar algo como esto.
Tabla prueba seria tu tabla.


DECLARE @MyInicio int, @MyFinal int, @MyContador int
SET @MyInicio = 1001
SET @MyFinal = (SELECT MAX(NUMERO) FROM PRUEBA)
SET @MyContador = @MyInicio
CREATE TABLE #LOSTSEQUENCE (MyID int)
WHILE @MyContador < @MyFinal
BEGIN
IF NOT EXISTS (SELECT Numero FROM Prueba WHERE Numero = @MyContador)
INSERT INTO #LOSTSEQUENCE VALUES(@MyContador)
SET @MyContador = @MyContador+1
CONTINUE
END
/*SELECT 'Series perdidas:'*/
SELECT MyID FROM #LOSTSEQUENCE

"Guillermo Villanueva" wrote in
message news:OlZet%
Me respondo solo:
lo puedo hacer con una consulta de la siguiente manera:
select A.fp_codigo, MIN(B.fp_codigo )
from FacturasPad A inner join FacturasPad B
on A.fp_codigo < B.fp_codigo

GROUP BY A.fp_codigo
HAVING MIN(B.fp_codigo) - A.fp_codigo > 7

El problema es que es bastante lento para devolverme el resultado, no
importa.

"Guillermo Villanueva" escribió en
el mensaje news:%23%
Buenas tardes, necesito desarrollar una función en mi base de datos.
Resulta que tengo códigos numéricos que teóricamente son secuenciales
(NO SON DE TIPO IDENTITY). pero en algunos casos se eliminan ciertos
rangos entonces me quedan cosas como:
fp_codigo
1
2
3
4
7
8
9
18
19
20
21
22
42
43
Necesito una función BuscarRango(x,desde,hasta) que me diga si es que
hay algún rango disponible de x o mas lugares, entonces la función me
devolvería verdadero si es que si hay y falso si no hay, y en caso de
que sea verdadero debería darme en desde, hasta el rango disponible,
ejemplo
BuscarRango(1000,desde,hasta) --> falso
BuscarRango(5,desde,hasta) --> verdadero 10 17

Se como hacerlo en powerbuilder pero no tengo la menor idea de como
hacerlo en transact lo cual sería mucho mejor. Desde ya muchas
gracias.

Guillermo

















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