Yii Framework Forum: [RESUELTO] Como acceder a una propiedad creada desde la consulta - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

[RESUELTO] Como acceder a una propiedad creada desde la consulta Rate Topic: -----

#1 User is offline   Jack Fiallos 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 256
  • Joined: 15-October 09
  • Location:Mexico

Posted 21 October 2010 - 08:22 PM

Estuve leyendo un rato sobre como utilizar SUM() desde las relaciones mediante STAT, pero tuve un par de problemas ya que no resulto realizarse una suma completa de todos los registros encontrados ya que el framework agrupa los resultados..

El codigo en mi modelo
class Lag extends CActiveRecord
{
  public function relations()
  {
    return array(
      'Total'=>array(self::STAT,'LagConcepts','lag_id','select'=>'SUM(tb_LagConcepts.amount)'),
    );
  }
}


El codigo en mi controlador
$Total = Lag::model()->with('Total')->findAll();


La consulta generada
SELECT `t`.`lag_id` AS `t0_c0` FROM `tb_lags` `t`

SELECT `lag_id` AS `c`,
SUM(tb_LagConcepts.amount) AS `s` 
FROM `tb_LagConcepts` WHERE (`tb_LagConcepts`.`lag_id` IN (1, 2))
GROUP BY `lag_id`

--+---
c | s
--+---
1 | 5
2 | 15


donde 'c' es la agrupacion que realiza por tabla_id y 's' la suma.. pero lo que busco es obtener un solo resultado, que seria la suma total de 5+15 = 20..
Celestic Dev Team
Yii Open Source Project Manager
0

#2 User is offline   sebas 

  • Advanced Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 496
  • Joined: 28-October 08
  • Location:Buenos Aires, Argentina

Posted 21 October 2010 - 10:18 PM

mmm, pero eso no es un sum de una relación, sino un sum de todos los items en total...

sin importar el ID...

Yo lo haría directo así (no se exacto si esto sale, pero es algo por el estilo):

LagConcepts::model()->find(array('select'=>'sum(amount) as qty');


En el modelo create una variable de clase $qty;

public $qty;


LagConcepts
0

#3 User is offline   Antonio Ramirez 

  • Elite Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 1,448
  • Joined: 04-October 10

Posted 22 October 2010 - 07:00 AM

Hay algo que no me cuadra en lo que muestras y es que

SELECT `t`.`lag_id` AS `t0_c0` FROM `tb_lags` `t`

SELECT `lag_id` AS `c`,
SUM(tb_LagConcepts.amount) AS `s` 
FROM `tb_LagConcepts` WHERE (`tb_LagConcepts`.`budget_id` IN (1, 2)) //<-- la relacion es asi? budget_id IN?
GROUP BY `lag_id`


No deberia ser?

'tb_LagConcepts'.id IN (1,2) ?

Can we see the relation rules on LagConcepts???
¿How long would it take for you to understand that you own nothing in this world?

www.ramirezcobos.com
www.2amigos.us
www.github.com/tonydspaniard
www.github.com/2amigos


Posted Image
0

#4 User is offline   Antonio Ramirez 

  • Elite Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 1,448
  • Joined: 04-October 10

Posted 22 October 2010 - 07:14 AM

Lo siento pero acabo de testear con mis modelos y funcion a la perfeccion, pienso sinceramente que tu problema es de mal declaradas relaciones:

1) Comprueba las relaciones entre tus modelos, si son ONExMANY, MANYxMANY, o de otra clase

2) Chequea que LagConcept y Lag tenga sus reglas de relacion bien.

3) Luego tu consulta en relations() esta bien...


Pero si las relaciones de tus objetos no son las correctas, olvídate... es normal que ocurra eso.


espero haber podido ayudar. si no lo consigues, siempre te queda escribir una funcion total() pero estas en el camino correcto. solo haz especial hincapie en tus relaciones, que estas esten creadas correctamente.

Un saludo!
¿How long would it take for you to understand that you own nothing in this world?

www.ramirezcobos.com
www.2amigos.us
www.github.com/tonydspaniard
www.github.com/2amigos


Posted Image
0

#5 User is offline   Antonio Ramirez 

  • Elite Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 1,448
  • Joined: 04-October 10

Posted 22 October 2010 - 07:15 AM

View Postsebas, on 21 October 2010 - 10:18 PM, said:

mmm, pero eso no es un sum de una relación, sino un sum de todos los items en total...

sin importar el ID...

Yo lo haría directo así (no se exacto si esto sale, pero es algo por el estilo):

LagConcepts::model()->find(array('select'=>'sum(amount) as qty');


En el modelo create una variable de clase $qty;

public $qty;


LagConcepts



La solucion es buena, pero en las relaciones Yii las agrupa correctamente por identificadores, no hace falta darles un identificador a no ser que el objeto sea de otra tabla no relacionada.

un saludo!
¿How long would it take for you to understand that you own nothing in this world?

www.ramirezcobos.com
www.2amigos.us
www.github.com/tonydspaniard
www.github.com/2amigos


Posted Image
0

#6 User is offline   Jack Fiallos 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 256
  • Joined: 15-October 09
  • Location:Mexico

Posted 22 October 2010 - 10:56 AM

Pues bien, siendo que al utilizar array(self::STAT) y SUM() decidi seguir la recomendacion de Sebas y hacer una consulta por separado.. la cual queda de la siguiente manera..

Desde este controlador invoco el modelo Lag y lo relaciono con LagConcepts, la consulta generada la realiza bien y hasta aqui sin problemas.
class TaskController extends Controller
{
  ...
  public function actionView()
  {
    $Total = Lag::model()->with('LagConcepts')->findAll(array(
      'select'=>'SUM(LagConcepts.amount) AS total',
    ));

    $this->render('view',array(
      'Cost'=>$Total,
    ));
  }
  ...
}


Segun indicaciones se debe de crear una propiedad publica en el modelo del cual estoy generando la consulta, en este caso Lag. Esta propiedad es el alias del resultado de la suma.
class Lag extends CActiveRecord
{
  public $total;
  ...
}


Y aqui es donde ya no comprendo.. porque al querer ver el resultado me genera un error porque no puedo acceder a total
Trying to get property of non-object
$Cost->total


Saben que me estoy perdiendo o que me falta ??
Celestic Dev Team
Yii Open Source Project Manager
0

#7 User is offline   sebas 

  • Advanced Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 496
  • Joined: 28-October 08
  • Location:Buenos Aires, Argentina

Posted 23 October 2010 - 12:45 PM

Fijate que lo que yo hago lo hago sobre lag concepts y no sobre lag.

Saludos,
0

#8 User is offline   sebas 

  • Advanced Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 496
  • Joined: 28-October 08
  • Location:Buenos Aires, Argentina

Posted 23 October 2010 - 12:46 PM

Además al hacer un findAll te devuelve un array, no un objeto... Por eso uso el find solo

También fijate de hacerlo sobre LagConcept directamente.
0

#9 User is offline   Jack Fiallos 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 256
  • Joined: 15-October 09
  • Location:Mexico

Posted 24 October 2010 - 10:25 AM

Al final lo unico que requeri hacer fue cambiar findAll() por un find() y la propiedad publica estaba bien en el modelo Lag, no fue necesario agregar una propiedad publica en el modelo LagConcepts.

Muchas gracias Sebas, el codigo ha funcionado muy bien.. y a ti tambien Antonio por tomarte el tiempo de revisar como resolverlo..
Celestic Dev Team
Yii Open Source Project Manager
0

#10 User is offline   Jack Fiallos 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 256
  • Joined: 15-October 09
  • Location:Mexico

Posted 25 October 2010 - 07:13 PM

Al parecer he encontrado un bug o error en el framework..

Pues sucede que despues de resolver el problema de utilizar la fx SUM() mi consulta no estaba lista para retornar datos validos.. Me refiero a que la consulta funcionaba bien siempre y cuando retornara un valor.. pero si no se retorna un valor el resultado sera nulo y ahi es donde me ocurre un error.

Entonces para evitar que la consulta retorne un valor nulo decidi utilizar IFNULL() y es donde se veo que algo anda mal..

Mas claro.. veamos el codigo..
class TaskController extends Controller
{
  ...
  public function actionView()
  {
    $Total = Lag::model()->with('LagConcepts')->findAll(array(
      'select'=>'IFNULL(SUM(LagConcepts.amount),0) AS total', // esta linea es la nueva
    ));

    $this->render('view',array(
      'Cost'=>$Total,
    ));
  }
  ...
}


Originalmente la consulta se construia bien antes de agregarle IFNULL y mas o menos quedaba asi..
SELECT SUM(LagConcepts.amount) AS total ...


Ahora despues de la modificacion parece faltarle algo
SELECT IFNULL(SUM(LagConcepts.amount) AS total


Claro esto deberia de quedar de la siguiente manera.. y lo que le falta es ",0)"
SELECT IFNULL(SUM(LagConcepts.amount),0) AS total


Es error mio, falta agregarle algo o hay algo con el framework que anda mal con la construccion de las consultas..
Celestic Dev Team
Yii Open Source Project Manager
0

#11 User is offline   Antonio Ramirez 

  • Elite Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 1,448
  • Joined: 04-October 10

Posted 26 October 2010 - 01:41 AM

yo creo que tu consulta es la correcta (--- aqui una variante: SUM(IF(columna IS NULL,0,columna)) ---)... por lo que dices parece que cuando es NULL ocurre un error, podemos ver el resultado de ese error? sería interesante verlo
¿How long would it take for you to understand that you own nothing in this world?

www.ramirezcobos.com
www.2amigos.us
www.github.com/tonydspaniard
www.github.com/2amigos


Posted Image
0

#12 User is offline   Jack Fiallos 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 256
  • Joined: 15-October 09
  • Location:Mexico

Posted 26 October 2010 - 10:01 AM

Antonio, intente resolver el problema implementando tu solucion pero no funciono.. genera exactamente el mismo error.

El codigo nuevamente modificado con tu propuesta
class TaskController extends Controller
{
  ...
  public function actionView()
  {
    $Total = Lag::model()->with('LagConcepts')->findAll(array(
      'select'=>'SUM(IF(LagConcepts.amount IS NULL,0,LagConcepts.amount)) AS total', //otra vez modifique esta linea
    ));

    $this->render('view',array(
      'Cost'=>$Total,
    ));
  }
  ...
}


Supuestamente la consulta deberia de quedar asi y no generar ningun error
SELECT SUM(IF(LagConcepts.amount IS NULL,0,LagConcepts.amount)) AS total ...


Pero la salida original del framework es esta y claro con un error de que la columna a la que estoy haciendo select no existe. Y pues no existe porque hace falta " IS NULL,0,LagConcepts.amount)) AS total"
Active record "Lag" is trying to select an invalid column "SUM(IF(LagConcepts.amount". Note, the column must exist in the table or be an expression with alias.


Ahora.. otra solucion que encontre fue dejar el codigo como inicialmente estaba funcionando y verificar que la variable retornada del select existiera, si no existe es porque un null es retornado por lo que forzo la variable total a tomar 0 e hice lo siguiente..
if (!isset($Cost->total))
  $Cost->total = 0;

$this->render('view',array(
  'Cost'=>$Cost,
));


Ok, esto funciona bien.. pero tendran alguna otra implementacion mas elegante y menos parchosa ??
Celestic Dev Team
Yii Open Source Project Manager
0

#13 User is offline   Antonio Ramirez 

  • Elite Member
  • Yii
  • Group: Yii Dev Team
  • Posts: 1,448
  • Joined: 04-October 10

Posted 26 October 2010 - 03:32 PM

Es normal que te de error:

public function actionView()
  {
    $Total = Lag::model()->with('LagConcepts')->findAll(array(
      'select'=>'SUM(IF(LagConcepts.amount IS NULL,0,LagConcepts.amount)) AS total', //otra vez modifique esta linea
    ));

    $this->render('view',array(
      'Cost'=>$Total,
    ));
  }


Estas creando un criterio sobre Lag que no es aplicable en este tipo de consulta puesto que es para LagConcepts. Creo que estamos liando la perdiz y podríamos hacerlo de otra manera muuuucho mas sencilla. Hazlo de la siguiente manera a ver que tal:

public function actionView()
  {
    // solo queremos el count estadistico, sin otros objetos (mucho mas rapido que de la otra forma)
    $dataReader = Yii::app()->db->createCommand('SELECT SUM({{lagconcepts}}.amount) AS total FROM {{lagconcepts}}')->query();
    
    // leemos la fila
    $row = $dataReader->read();

    // muestro en view
    $this->render('view',array(
      'Cost'=>$row['total'],
    ));
  }




Seguro que asi te funciona de maravilla
¿How long would it take for you to understand that you own nothing in this world?

www.ramirezcobos.com
www.2amigos.us
www.github.com/tonydspaniard
www.github.com/2amigos


Posted Image
0

#14 User is offline   Jack Fiallos 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 256
  • Joined: 15-October 09
  • Location:Mexico

Posted 26 October 2010 - 05:15 PM

Probe tu codigo y si.. si funciono solo que tuve que realizar toda la consulta yo mismo y pues usando un framework es de esas cosas en las que casi no deberia de intervenir..

En fin.. deje la solución que encontre inicialmente.. aunque ahora queda registrada que se puede lograr de ambas maneras..

Muchas gracias por las respuestas, saludos
Celestic Dev Team
Yii Open Source Project Manager
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users