Obtener tantas líneas como valor en un campo (2009/09/07)

07/09/2009 - 12:38 por Mauricio | Informe spam
Hola a todos,
tengo esta select:
SELECT PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,
PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR, OL_Portion_Size, OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' + CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1))))
AS PORTION_TEXT,
PRO_CODE, FT_NUMBER, OL_QUANTITY
FROM MCS_ORDERLINES, MCS_ORDERS, MCS_PRODUCTS, MCS_FoodTypes
WHERE OL_ORD_ID = ORD_ID AND
OL_PRO_ID = PRO_ID AND
OL_FT_ID = FT_ID AND
OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59'

Para este día en particular tengo solo 1 registro y el valor en la
columna OL_QUANTITY es 2.
Cómo puedo hacer para obtener tantas líneas de resultado como valor
tenga en la columna OL_QUANTITY? En este caso, por ejemplo, debería
obtener 2 líneas, exactamente iguales.
Gracias a todos por la ayuda.
Saludos.

Mauricio
Copenhague, Dinamarca

Preguntas similare

Leer las respuestas

#1 Ruben Garrigos
07/09/2009 - 13:44 | Informe spam
Hola Mauricio,

Para solucionar tu necesidad te sería muy util que tuvieras una tabla de
números contra la que cruzar tu tabla. Esta tabla de números puede ser bien
física o bien autogenerada aunque ello te consuma una cierta cantidad de CPU.

Un ejemplillo de cómo hacer esto que te planteo es el siguiente, adáptalo
a tu tabla y necesidades concretas:

create table test (id int primary key,filas int);
insert into test values (1,1),(2,3),(3,4);
select test.* from test
join
(
SELECT n
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY object_id )
FROM sys.objects ) D ( n )
WHERE n <= 100
) num100
on filas >= n;

Ten en cuenta que el ejemplo funcionará solo hasta 100 filas como máximo
pues es ese el tamaño de la tabla de números generada. También ten en cuenta
que en el ejemplo he utilizado sintaxis de SQL 2008 por lo que puede que
tengas que hacer algún cambio para adaptarlo a tu versión.

Un saludo,

Rubén Garrigós
Solid Quality Mentors

Blog: http://blogs.solidq.com/es/elrincondeldba

Hola a todos,
tengo esta select:
SELECT PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,
PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR, OL_Portion_Size,
OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' + CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1))))
AS PORTION_TEXT,
PRO_CODE, FT_NUMBER, OL_QUANTITY
FROM MCS_ORDERLINES, MCS_ORDERS, MCS_PRODUCTS, MCS_FoodTypes
WHERE OL_ORD_ID = ORD_ID AND
OL_PRO_ID = PRO_ID AND
OL_FT_ID = FT_ID AND
OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59'
Para este día en particular tengo solo 1 registro y el valor en la
columna OL_QUANTITY es 2.
Cómo puedo hacer para obtener tantas líneas de resultado como valor
tenga en la columna OL_QUANTITY? En este caso, por ejemplo, debería
obtener 2 líneas, exactamente iguales.
Gracias a todos por la ayuda.
Saludos
Respuesta Responder a este mensaje
#2 Mauricio
07/09/2009 - 13:57 | Informe spam
Hola Rubén,
gracias por tu respuesta pero quería evitar precisamente eso, tener
que crear tablas auxiliares. Sé que no es fácil lo que quiero hacer,
voy a ver si encuentro la forma.
Saludos.

Ruben Garrigos a émis l'idée suivante :
Hola Mauricio,

Para solucionar tu necesidad te sería muy util que tuvieras una tabla de
números contra la que cruzar tu tabla. Esta tabla de números puede ser bien
física o bien autogenerada aunque ello te consuma una cierta cantidad de CPU.

Un ejemplillo de cómo hacer esto que te planteo es el siguiente, adáptalo a
tu tabla y necesidades concretas:

create table test (id int primary key,filas int);
insert into test values (1,1),(2,3),(3,4);
select test.* from test
join
(
SELECT n
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY object_id )
FROM sys.objects ) D ( n )
WHERE n <= 100 ) num100
on filas >= n;

Ten en cuenta que el ejemplo funcionará solo hasta 100 filas como máximo pues
es ese el tamaño de la tabla de números generada. También ten en cuenta que
en el ejemplo he utilizado sintaxis de SQL 2008 por lo que puede que tengas
que hacer algún cambio para adaptarlo a tu versión.

Un saludo,

Rubén Garrigós
Solid Quality Mentors

Blog: http://blogs.solidq.com/es/elrincondeldba

Hola a todos,
tengo esta select:
SELECT PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,
PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR, OL_Portion_Size,
OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' + CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1))))
AS PORTION_TEXT,
PRO_CODE, FT_NUMBER, OL_QUANTITY
FROM MCS_ORDERLINES, MCS_ORDERS, MCS_PRODUCTS, MCS_FoodTypes
WHERE OL_ORD_ID = ORD_ID AND
OL_PRO_ID = PRO_ID AND
OL_FT_ID = FT_ID AND
OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59'
Para este día en particular tengo solo 1 registro y el valor en la
columna OL_QUANTITY es 2.
Cómo puedo hacer para obtener tantas líneas de resultado como valor
tenga en la columna OL_QUANTITY? En este caso, por ejemplo, debería
obtener 2 líneas, exactamente iguales.
Gracias a todos por la ayuda.
Saludos.





Mauricio
Copenhague, Dinamarca
Respuesta Responder a este mensaje
#3 Alejandro Mesa
07/09/2009 - 17:25 | Informe spam
Apoyo lo dicho por Ruben. A la final sera mas el beneficio de usar la tabla
auxiliar de numeros, que el costo de generarla.

Tambien puedes crear una funcion que devuelva la tabla de numeros. Mira esta
funcion propuesta por el amestro Itzik Ben-Gan, quien es colega de Ruben en
Solid Quality Mentors.

CREATE FUNCTION dbo.fn_nums(@n AS bigint) RETURNS TABLE AS
RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY 1) AS n FROM L5)
SELECT n FROM Nums WHERE n <= @n;
GO

SELECT
PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR,
OL_Portion_Size, OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' + CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1)))) AS PORTION_TEXT, PRO_CODE, FT_NUMBER, OL_QUANTITY
FROM
MCS_ORDERLINES
inner join
MCS_ORDERS
OL_ORD_ID = ORD_ID
inner join
MCS_PRODUCTS
OL_PRO_ID = PRO_ID
inner join
MCS_FoodTypes
OL_FT_ID = FT_ID
cross apply
dbo.fn_nums(OL_QUANTITY) as F(n)
WHERE
OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59';


AMB


"Ruben Garrigos" wrote:

Hola Mauricio,

La alternativa que te plantee no utiliza tablas temporales. Únicamente te
comenté que el tener una tabla con números es muy útil para solucionar este
y otros problemas de forma eficiente. Ya cada uno decide que costes está
dispuesto a pagar en la generación de dicha tabla de números cada caso (autogenerarla
o mantenerla ya generada)

Un saludo,

Rubén Garrigós
Solid Quality Mentors

Blog: http://blogs.solidq.com/es/elrincondeldba

> Hola Rubén,
> gracias por tu respuesta pero quería evitar precisamente eso, tener
> que crear tablas auxiliares. Sé que no es fácil lo que quiero hacer,
> voy a ver si encuentro la forma.
> Saludos.
> Ruben Garrigos a émis l'idée suivante :
>
>> Hola Mauricio,
>>
>> Para solucionar tu necesidad te sería muy util que tuvieras una tabla
>> de números contra la que cruzar tu tabla. Esta tabla de números puede
>> ser bien física o bien autogenerada aunque ello te consuma una cierta
>> cantidad de CPU.
>>
>> Un ejemplillo de cómo hacer esto que te planteo es el siguiente,
>> adáptalo a tu tabla y necesidades concretas:
>>
>> create table test (id int primary key,filas int);
>> insert into test values (1,1),(2,3),(3,4);
>> select test.* from test
>> join
>> (
>> SELECT n
>> FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY object_id )
>> FROM sys.objects ) D ( n )
>> WHERE n <= 100 ) num100
>> on filas >= n;
>> Ten en cuenta que el ejemplo funcionará solo hasta 100 filas como
>> máximo pues es ese el tamaño de la tabla de números generada. También
>> ten en cuenta que en el ejemplo he utilizado sintaxis de SQL 2008 por
>> lo que puede que tengas que hacer algún cambio para adaptarlo a tu
>> versión.
>>
>> Un saludo,
>>
>> Rubén Garrigós
>> Solid Quality Mentors
>> Blog: http://blogs.solidq.com/es/elrincondeldba
>>
>>> Hola a todos,
>>> tengo esta select:
>>> SELECT PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK,
>>> PRO_LABEL_TEXT,
>>> PRO_HOWTOKEEP,
>>> PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR, OL_Portion_Size,
>>> OL_Quantity,
>>> (SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
>>> FROM dbo.MCS_Config
>>> WHERE (CFG_Section = 'RECIPES') AND
>>> (CFG_Field = 'PORTION_SIZE_' +
>>> CAST(dbo.MCS_OrderLines.OL_Portion_size
>>> AS char(1))))
>>> AS PORTION_TEXT,
>>> PRO_CODE, FT_NUMBER, OL_QUANTITY
>>> FROM MCS_ORDERLINES, MCS_ORDERS, MCS_PRODUCTS, MCS_FoodTypes
>>> WHERE OL_ORD_ID = ORD_ID AND
>>> OL_PRO_ID = PRO_ID AND
>>> OL_FT_ID = FT_ID AND
>>> OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59'
>>> Para este día en particular tengo solo 1 registro y el valor en la
>>> columna OL_QUANTITY es 2.
>>> Cómo puedo hacer para obtener tantas líneas de resultado como valor
>>> tenga en la columna OL_QUANTITY? En este caso, por ejemplo, debería
>>> obtener 2 líneas, exactamente iguales.
>>> Gracias a todos por la ayuda.
>>> Saludos.



Respuesta Responder a este mensaje
#4 Mauricio
08/09/2009 - 14:47 | Informe spam
Rubén, Alejandro,
gracias por sus respuestas. Estoy intentando con la función sugerida
por Alejandro y tengo solo un "pequeño" problema.
Si ejecuto esto:
SELECT
PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR,
OL_Portion_Size, OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' +
CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1)))) AS PORTION_TEXT, PRO_CODE, FT_NUMBER, OL_QUANTITY AS
CANTIDAD
FROM
MCS_ORDERLINES
inner join
MCS_ORDERS ON
OL_ORD_ID = ORD_ID
inner join
MCS_PRODUCTS ON
OL_PRO_ID = PRO_ID
inner join
MCS_FoodTypes ON
OL_FT_ID = FT_ID
cross apply
dbo.fn_Nros(2)
WHERE
OL_DATE BETWEEN '20090908 00:00:00' AND '20090908 23:59:59' AND
OL_FOOD_REMARK IS NOT NULL;

Obtengo 2 líneas inmediatamente, que es el parámetro que le pasé a
la función dbo.fn_Nros.

Pero si en lugar de pasar 2 paso el valor del campo, el query
parece no ejecutarse o al menos pasado 20 segundos no arroja ningún
valor (cancelé la ejecución, pasando el número es instantáneo el
resultado).

Este es el query que no se ejecuta.
SELECT
PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR,
OL_Portion_Size, OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' +
CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1)))) AS PORTION_TEXT, PRO_CODE, FT_NUMBER, OL_QUANTITY AS
CANTIDAD
FROM
MCS_ORDERLINES
inner join
MCS_ORDERS ON
OL_ORD_ID = ORD_ID
inner join
MCS_PRODUCTS ON
OL_PRO_ID = PRO_ID
inner join
MCS_FoodTypes ON
OL_FT_ID = FT_ID
cross apply
dbo.fn_Nros(OL_QUANTITY)
WHERE
OL_DATE BETWEEN '20090908 00:00:00' AND '20090908 23:59:59' AND
OL_FOOD_REMARK IS NOT NULL;

Por qué no puedo pasar el campo como parámetro? Es un int, la
función recibe un bigint, intenté convertirlo con cast pero es lo
mismo.

Alguna idea?

Gracias nuevamente.


Alejandro Mesa a formulé la demande :
Apoyo lo dicho por Ruben. A la final sera mas el beneficio de usar la tabla
auxiliar de numeros, que el costo de generarla.

Tambien puedes crear una funcion que devuelva la tabla de numeros. Mira esta
funcion propuesta por el amestro Itzik Ben-Gan, quien es colega de Ruben en
Solid Quality Mentors.

CREATE FUNCTION dbo.fn_nums(@n AS bigint) RETURNS TABLE AS
RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY 1) AS n FROM L5)
SELECT n FROM Nums WHERE n <= @n;
GO

SELECT
PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR,
OL_Portion_Size, OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' + CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1)))) AS PORTION_TEXT, PRO_CODE, FT_NUMBER, OL_QUANTITY
FROM
MCS_ORDERLINES
inner join
MCS_ORDERS
OL_ORD_ID = ORD_ID
inner join
MCS_PRODUCTS
OL_PRO_ID = PRO_ID
inner join
MCS_FoodTypes
OL_FT_ID = FT_ID
cross apply
dbo.fn_nums(OL_QUANTITY) as F(n)
WHERE
OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59';


AMB


"Ruben Garrigos" wrote:

Hola Mauricio,

La alternativa que te plantee no utiliza tablas temporales. Únicamente te
comenté que el tener una tabla con números es muy útil para solucionar este
y otros problemas de forma eficiente. Ya cada uno decide que costes está
dispuesto a pagar en la generación de dicha tabla de números cada caso
(autogenerarla o mantenerla ya generada)

Un saludo,

Rubén Garrigós
Solid Quality Mentors

Blog: http://blogs.solidq.com/es/elrincondeldba

Hola Rubén,
gracias por tu respuesta pero quería evitar precisamente eso, tener
que crear tablas auxiliares. Sé que no es fácil lo que quiero hacer,
voy a ver si encuentro la forma.
Saludos.
Ruben Garrigos a émis l'idée suivante :

Hola Mauricio,

Para solucionar tu necesidad te sería muy util que tuvieras una tabla
de números contra la que cruzar tu tabla. Esta tabla de números puede
ser bien física o bien autogenerada aunque ello te consuma una cierta
cantidad de CPU.

Un ejemplillo de cómo hacer esto que te planteo es el siguiente,
adáptalo a tu tabla y necesidades concretas:

create table test (id int primary key,filas int);
insert into test values (1,1),(2,3),(3,4);
select test.* from test
join
(
SELECT n
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY object_id )
FROM sys.objects ) D ( n )
WHERE n <= 100 ) num100
on filas >= n;
Ten en cuenta que el ejemplo funcionará solo hasta 100 filas como
máximo pues es ese el tamaño de la tabla de números generada. También
ten en cuenta que en el ejemplo he utilizado sintaxis de SQL 2008 por
lo que puede que tengas que hacer algún cambio para adaptarlo a tu
versión.

Un saludo,

Rubén Garrigós
Solid Quality Mentors
Blog: http://blogs.solidq.com/es/elrincondeldba

Hola a todos,
tengo esta select:
SELECT PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK,
PRO_LABEL_TEXT,
PRO_HOWTOKEEP,
PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR, OL_Portion_Size,
OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' +
CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1))))
AS PORTION_TEXT,
PRO_CODE, FT_NUMBER, OL_QUANTITY
FROM MCS_ORDERLINES, MCS_ORDERS, MCS_PRODUCTS, MCS_FoodTypes
WHERE OL_ORD_ID = ORD_ID AND
OL_PRO_ID = PRO_ID AND
OL_FT_ID = FT_ID AND
OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59'
Para este día en particular tengo solo 1 registro y el valor en la
columna OL_QUANTITY es 2.
Cómo puedo hacer para obtener tantas líneas de resultado como valor
tenga en la columna OL_QUANTITY? En este caso, por ejemplo, debería
obtener 2 líneas, exactamente iguales.
Gracias a todos por la ayuda.
Saludos.














Mauricio
Copenhague, Dinamarca
Respuesta Responder a este mensaje
#5 Alejandro Mesa
08/09/2009 - 18:49 | Informe spam
Mauricio,

Por alguna razon que desconozco, el optimizador se pierde con la llamada a
la funcion.

1 - Trata modificando la funcion y usando solo hasta el nivel 3 que te
permite hasta 256 #s.

Si no te funciona, trata entonces creando la tabla de #s como aconsejo Ruben
en su post, y usa un join como "n.numero <= OL_QUANTITY".


AMB


"Mauricio" wrote:

Rubén, Alejandro,
gracias por sus respuestas. Estoy intentando con la función sugerida
por Alejandro y tengo solo un "pequeño" problema.
Si ejecuto esto:
SELECT
PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR,
OL_Portion_Size, OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' +
CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1)))) AS PORTION_TEXT, PRO_CODE, FT_NUMBER, OL_QUANTITY AS
CANTIDAD
FROM
MCS_ORDERLINES
inner join
MCS_ORDERS ON
OL_ORD_ID = ORD_ID
inner join
MCS_PRODUCTS ON
OL_PRO_ID = PRO_ID
inner join
MCS_FoodTypes ON
OL_FT_ID = FT_ID
cross apply
dbo.fn_Nros(2)
WHERE
OL_DATE BETWEEN '20090908 00:00:00' AND '20090908 23:59:59' AND
OL_FOOD_REMARK IS NOT NULL;

Obtengo 2 líneas inmediatamente, que es el parámetro que le pasé a
la función dbo.fn_Nros.

Pero si en lugar de pasar 2 paso el valor del campo, el query
parece no ejecutarse o al menos pasado 20 segundos no arroja ningún
valor (cancelé la ejecución, pasando el número es instantáneo el
resultado).

Este es el query que no se ejecuta.
SELECT
PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
PRO_HOWTOKEEP,PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR,
OL_Portion_Size, OL_Quantity,
(SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
FROM dbo.MCS_Config
WHERE (CFG_Section = 'RECIPES') AND
(CFG_Field = 'PORTION_SIZE_' +
CAST(dbo.MCS_OrderLines.OL_Portion_size
AS char(1)))) AS PORTION_TEXT, PRO_CODE, FT_NUMBER, OL_QUANTITY AS
CANTIDAD
FROM
MCS_ORDERLINES
inner join
MCS_ORDERS ON
OL_ORD_ID = ORD_ID
inner join
MCS_PRODUCTS ON
OL_PRO_ID = PRO_ID
inner join
MCS_FoodTypes ON
OL_FT_ID = FT_ID
cross apply
dbo.fn_Nros(OL_QUANTITY)
WHERE
OL_DATE BETWEEN '20090908 00:00:00' AND '20090908 23:59:59' AND
OL_FOOD_REMARK IS NOT NULL;

Por qué no puedo pasar el campo como parámetro? Es un int, la
función recibe un bigint, intenté convertirlo con cast pero es lo
mismo.

Alguna idea?

Gracias nuevamente.


Alejandro Mesa a formulé la demande :
> Apoyo lo dicho por Ruben. A la final sera mas el beneficio de usar la tabla
> auxiliar de numeros, que el costo de generarla.
>
> Tambien puedes crear una funcion que devuelva la tabla de numeros. Mira esta
> funcion propuesta por el amestro Itzik Ben-Gan, quien es colega de Ruben en
> Solid Quality Mentors.
>
> CREATE FUNCTION dbo.fn_nums(@n AS bigint) RETURNS TABLE AS
> RETURN
> WITH
> L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
> L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
> L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
> L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
> L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
> L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
> Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY 1) AS n FROM L5)
> SELECT n FROM Nums WHERE n <= @n;
> GO
>
> SELECT
> PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK, PRO_LABEL_TEXT,
> PRO_HOWTOKEEP,PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR,
> OL_Portion_Size, OL_Quantity,
> (SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
> FROM dbo.MCS_Config
> WHERE (CFG_Section = 'RECIPES') AND
> (CFG_Field = 'PORTION_SIZE_' + CAST(dbo.MCS_OrderLines.OL_Portion_size
> AS char(1)))) AS PORTION_TEXT, PRO_CODE, FT_NUMBER, OL_QUANTITY
> FROM
> MCS_ORDERLINES
> inner join
> MCS_ORDERS
> OL_ORD_ID = ORD_ID
> inner join
> MCS_PRODUCTS
> OL_PRO_ID = PRO_ID
> inner join
> MCS_FoodTypes
> OL_FT_ID = FT_ID
> cross apply
> dbo.fn_nums(OL_QUANTITY) as F(n)
> WHERE
> OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59';
>
>
> AMB
>
>
> "Ruben Garrigos" wrote:
>
>> Hola Mauricio,
>>
>> La alternativa que te plantee no utiliza tablas temporales. Únicamente te
>> comenté que el tener una tabla con números es muy útil para solucionar este
>> y otros problemas de forma eficiente. Ya cada uno decide que costes está
>> dispuesto a pagar en la generación de dicha tabla de números cada caso
>> (autogenerarla o mantenerla ya generada)
>>
>> Un saludo,
>>
>> Rubén Garrigós
>> Solid Quality Mentors
>>
>> Blog: http://blogs.solidq.com/es/elrincondeldba
>>
>>> Hola Rubén,
>>> gracias por tu respuesta pero quería evitar precisamente eso, tener
>>> que crear tablas auxiliares. Sé que no es fácil lo que quiero hacer,
>>> voy a ver si encuentro la forma.
>>> Saludos.
>>> Ruben Garrigos a émis l'idée suivante :
>>>
>>>> Hola Mauricio,
>>>>
>>>> Para solucionar tu necesidad te sería muy util que tuvieras una tabla
>>>> de números contra la que cruzar tu tabla. Esta tabla de números puede
>>>> ser bien física o bien autogenerada aunque ello te consuma una cierta
>>>> cantidad de CPU.
>>>>
>>>> Un ejemplillo de cómo hacer esto que te planteo es el siguiente,
>>>> adáptalo a tu tabla y necesidades concretas:
>>>>
>>>> create table test (id int primary key,filas int);
>>>> insert into test values (1,1),(2,3),(3,4);
>>>> select test.* from test
>>>> join
>>>> (
>>>> SELECT n
>>>> FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY object_id )
>>>> FROM sys.objects ) D ( n )
>>>> WHERE n <= 100 ) num100
>>>> on filas >= n;
>>>> Ten en cuenta que el ejemplo funcionará solo hasta 100 filas como
>>>> máximo pues es ese el tamaño de la tabla de números generada. También
>>>> ten en cuenta que en el ejemplo he utilizado sintaxis de SQL 2008 por
>>>> lo que puede que tengas que hacer algún cambio para adaptarlo a tu
>>>> versión.
>>>>
>>>> Un saludo,
>>>>
>>>> Rubén Garrigós
>>>> Solid Quality Mentors
>>>> Blog: http://blogs.solidq.com/es/elrincondeldba
>>>>
>>>>> Hola a todos,
>>>>> tengo esta select:
>>>>> SELECT PRO_DESCRIPTION_LABEL, FT_NAME, OL_FOOD_REMARK,
>>>>> PRO_LABEL_TEXT,
>>>>> PRO_HOWTOKEEP,
>>>>> PRO_HOWTOPREPARE, PRO_DAYSINREFRIGERATOR, OL_Portion_Size,
>>>>> OL_Quantity,
>>>>> (SELECT CAST(CFG_Value AS varchar(20)) AS Expr1
>>>>> FROM dbo.MCS_Config
>>>>> WHERE (CFG_Section = 'RECIPES') AND
>>>>> (CFG_Field = 'PORTION_SIZE_' +
>>>>> CAST(dbo.MCS_OrderLines.OL_Portion_size
>>>>> AS char(1))))
>>>>> AS PORTION_TEXT,
>>>>> PRO_CODE, FT_NUMBER, OL_QUANTITY
>>>>> FROM MCS_ORDERLINES, MCS_ORDERS, MCS_PRODUCTS, MCS_FoodTypes
>>>>> WHERE OL_ORD_ID = ORD_ID AND
>>>>> OL_PRO_ID = PRO_ID AND
>>>>> OL_FT_ID = FT_ID AND
>>>>> OL_DATE BETWEEN '20090907 00:00:00' AND '20090907 23:59:59'
>>>>> Para este día en particular tengo solo 1 registro y el valor en la
>>>>> columna OL_QUANTITY es 2.
>>>>> Cómo puedo hacer para obtener tantas líneas de resultado como valor
>>>>> tenga en la columna OL_QUANTITY? En este caso, por ejemplo, debería
>>>>> obtener 2 líneas, exactamente iguales.
>>>>> Gracias a todos por la ayuda.
>>>>> Saludos.
>>
>>
>>

Mauricio
Copenhague, Dinamarca



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