[Resolvido] Como utilizar um SQL complexo

O sistema de montagem de consultas do Yii é prático e conveniente, mas não tem jeito, uma alternativa assim nunca poderá cobrir todas possíbilidades de complexidade de SQL.

Bem… preciso fazer uma consulta que utiliza duas sub-consultas, entre outras complexidades.

Gostaria de saber como introduzir o SQL ‘tradicional’ na consulta do Yii (num model).

O SQL é este abaixo.

Se alguém me explicar como converte-lo para o modo de consultas do Yii, pode ser também.

Não tenho preconceito quanto ao tipo de solução.


SELECT Fantasia, DATA

FROM (

	SELECT Fantasia, Data_Cadastro, DT, DV

	,CASE WHEN ((DT IS NULL) AND (DV IS NULL)) 

		THEN Data_Cadastro 

		ELSE CASE WHEN (DV IS NULL) OR (DT > DV) THEN DT ELSE DV END		

	END DATA

	FROM cadastro

	LEFT JOIN 

		(

		SELECT Cod_Conta, MAX(Data_Cadastro) DT

			FROM tarefa

			WHERE Cod_Vendedor = 439

			GROUP BY Cod_Conta

	    ) TF ON TF.Cod_Conta = cadastro.Cod_Cadastro   

	LEFT JOIN 

		(

		SELECT Cod_Conta, MAX(Data_Cadastro) DV

			FROM contato_visita

			WHERE Cod_Vendedor = 439

			GROUP BY Cod_Conta

	    ) V ON V.Cod_Conta = cadastro.Cod_Cadastro

	WHERE StatusConta = 'Em Andamento'

	AND Cod_Vendedor = 439

	AND Data_Expirou IS NULL

) X

WHERE X.Data < (CURDATE()-10)

ORDER BY DATA

Essa consulta mostra registros que não foram atualizados nos últimos 10 dias

E a atualização pode ser realizada em tres tabelas diferentes.

Mesmo usando Yii, é possível interagir com o banco de dados de forma mais "direta" usando:




$q = 'SELECT * FROM table_name';

$cmd = Yii::app()->db->createCommand($q);

$result = $cmd->query();



O método query() citado acima vai retornar um objeto CDbDataReader, que pode ser usado num loop:




foreach ($result as $row) {

	echo $row['column_name'];

}



Mas caso queira trabalhar com seus próprios objetos, pode fazer algo como:




$q = 'SELECT * FROM table_name WHERE id=1';

$cmd = Yii::app()->db->createCommand($q);

$cmd->setFetchMode(PDO::FETCH_CLASS, 'Model_name');

$model = $cmd->queryRow();

// Use $model->attribute_name para acessar os valores retornados



Note a diferença em usar o método query() e queryRow(). Este último é usado quando se faz uma consulta ao banco de dados para retornar apenas um registro.

Mais informações em: http://www.yiiframew…en/database.dao

[quote="Ednei"]Note a diferença em usar o método query() e queryRow(). Este último é usado quando se faz uma consulta ao banco de dados para retornar apenas um registro.
[/quote]

Obrigado Ednei

Eu gostaria de retornar a informação se for possível, utilizando o tipo de dados "[color="#FF0000"]CActiveDataProvider[/color]"

Que é o tipo de dados que é utilizado com o "bootstrap.widgets.TbGridView"

Como nesta linha => ‘dataProvider’=>$tarefaModel->proximas_tarefas(),

Aqui o trecho de código da função proximas_tarefas, que retorna a informação


		return $dataProvider=new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

			'sort'=>false,

			'pagination' => false,

		));

Obs. procurei no link que disponibilizasse e não encontrei

CSqlDataProvider implementa o dataProvider baseado em consultas SQL (http://www.yiiframework.com/doc/api/1.1/CSqlDataProvider/)

Mas tem este tutorial que explica melhor como usar o recurso do CSqlDataProvider no lugar do CActiveDataProvider: http://www.yiiframework.com/wiki/462/yii-for-beginners-2#hh8 (mas em inglês!).

Caso não consiga entender me avise!

Graças a tua dica consegui ir adiante na tarefa

Mas agora encontrei um outro problema, mais de lógica…

Conforme o resultado da consulta devo MOSTRAR ou NÃO MOSTRAR

uma lista com os dados…

Ou seja, teria que obter a QUANTIDADE de registros da consulta

e depois mostrar OS REGISTROS, somente se a quantidade for ACIMA DE ZERO

Poderia fazer a consulta duas vezes, mas pela lógica isto acabaria pesando a página…

Tem alguma ideia de como fazer?

Se fosse algo como um "recordset" (em outras linguagens) daria pra ver a quantidade, e mostrar depois.

Mas sendo um dataProvider … ai já não sei… ???

O objeto CDataProvider possui alguns métodos públicos que podem ajudar:

http://www.yiiframework.com/doc/api/1.1/CDataProvider#getTotalItemCount-detail

http://www.yiiframework.com/doc/api/1.1/CDataProvider#getItemCount-detail

http://www.yiiframework.com/doc/api/1.1/CDataProvider#getData-detail

Eu resolvi assim

no index


$SemNovimento = $contaModel->ContasSemMovimento($Cod_Vendedor);

Chamo a função ContasSemMovimento que retorna um objeto tipo List (eu acho)


$list = Yii::app()->db->createCommand($sql)->queryAll();

Aí (no index denovo) percorro o objeto item a item e mostro

ou seja utilizei a tecnologia antiga… (eu acho)


                                $Zebra = array(1=>"odd",2=>"even");

                                $vez=0;

                                foreach ($SemNovimento as $item) {

                                    $myDateTime = date("d/m/Y", strtotime($item['DATA']));

                                    $vez+=1;

                                    echo '<tr class="'.$Zebra[1].'"><td>'.$myDateTime.' - </td><td><a href="http://www.sbstore.com.br/sistema/crm/conta/update/'.$item['Cod_Cadastro'].'/">'.$item['Fantasia'].'</a></Br></td></tr>';

                                    

                                    if ($vez==3) {$vez=1;}

                                }

                                if ($vez==0) {

                                	echo 'N&atilde;o foram realizados cadastros, tarefas ou vizitas';

                                }