what would be the best way (or any way, because I can't figure out anything blending with Phalcon models at the moment) to fetch data from query like this:
SELECT *, (select sum(l.log_volume) from logs l where l.parcel_id = p.parcel_id) as parcel_total_volume
FROM PARCELS p
what I want is to basically have calculated fields easily accessible from model, preferably calculated on sql side and fetched with every record.
If this must be done in model php code instead, then how?
I would go for something like this:
<?php
class Parcels extends Phalcon\Mvc\Model
{
private static $sumsCache = [];
/*
...
*/
public function getTotalVolume()
{
if(!isset($sumsCache[$this->parcel_id])) {
$sumsCache[$this->parcel_id] = Logs::sum("parcel_id = $this->parcel_id");
}
return $sumsCache[$this->parcel_id];
}
}
This way you fetch the sum JIT and you store a static cache for each parcel_id.
Related
The only data that should appear when I click the "view data button" should be the employee's personal data by searching its employee id.
This is my code:
public void viewAll() {
btnview.setOnClickListener(
new View.OnClickListener() {
#Override`enter code here`
public void onClick(View v) {
Cursor res = EmployeeData.getAllData();
if(res.getCount() == 0) {
// show message
showMessage("Error","Nothing found");
return;}
How can I get the specific data from the existing database?
You need to replace the getAllData with a method that SELECTs the appropriate data using a WHERE clause which is invoked with the employeeId being passed to it (after extracting the employeeId from the clicked item ).
You then need to process the Cursor by extracting the data from it, if any exists.
So you could have something like the following in your class that extends SQLiteOpenHelper :-
public Cursor getEmployeeDataById(long id) {
return this.getWritableDatabase().query("the_table",null,"employeeId=?",new String[]{String.valueOf(id)},null, null,null);
}
obviously "the_table" and "employeeId" should be replaced by the actual names.
see Query for an explanation of the method's parameters.
the Query (method which has 4 signatures) is a convenience method that returns a Cursor object.
-It generates the SQL on your behalf e.g. the above would generate the SQL SELECT * FROM the_table WHERE employeeId=?
- where the ? is bound (prevents SQL Injection) to the passed id value by SQLite.
When extracting the data from the Cursor, rather than checking the count, you can rely upon the fact that the Cursor's will return false if it cannot move to the first row (i.e. there is no first row). So extracting the data could be along the lines of:-
Cursor csr = EmployeeData.getEmployeeDataById(extracted_employee_id);
if (csr.moveToFirst()) {
.... extract the data from the cursor
} else {
showMessage("Error","Nothing found");
}
I'm developing a backend application on Spring Boot 2 and Croud Repository.
I have a table called MoneyTransfer, and table has columns called customerId and firmId.
I need to get last 10 different firms that customer transferred money.
Currently, I get users all money transfers and filter them. However, this method doesn't make sense because I get all elements in the database to find last 10. It may cause performance problem.
fun getList(customerId: String) {
var list = mutableListOf<MoneyTransfer>()
moneyTransferRepository.findByCustomerId(customerId).forEach {
if (list.find(elem -> it.firmId == elem.firmId) == null) {
list.add(it)
}
if (list.size == 10) {
return#forEach
}
}
return list
}
Do you have any efficient solutuion that let me get last 10 different firmId without getting all database row?
If you are using Spring Data along with Spring Boot, you can create a SQL Query to retrieve only the records you want and use it with #Query annotations.
For example:
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}
Documentation here: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.at-query
Create custom #Query with pagination, this will help you optimize the query without getting all database row
#Repository
public interface MoneyTransferRepository extends CrudRepository<MoneyTransfer, String> {
#Query("SELECT m.firmId FROM MoneyTransfer m WHERE m.customerId = :customerId ORDER BY m.id DESC")
List<String> findFirmIdsByCustomerId(#Param("customerId") String customerId, Pageable pageable);
}
But you still will have to check the result with deferent firmId and check the result size of deferent firmIds, if it's less than 10 then in your case you will again make a request to the database and change page in PageRequest
moneyTransferRepository.findFirmIdsByCustomerId(customerId, PageRequest.of(0, 10));
P.S. I also tried this with DISTINCT but it ignores all duplicated firmId with the same customerId
Try this way (i'm not sure - can not test right now)
public interface MoneyTransferRepository extends JpaRepository<MoneyTransfer, Long> {
MoneyTransfer findFirst10ByCustomerIdDesc(String customerId);
}
And sort result reverse in getList method
I wonder if it possible to write a user-defined store function for PIG that iterates twice over the data / input tuples.
I read here http://pig.apache.org/docs/r0.7.0/udf.html#Store+Functions how to write your own store function, e.g. by implementing your own "getNext()" method.
For my use case, however, it is necessary to see every tuple twice in the "getNext()" method, so I wonder whether there is a way to that, for example by reseting the reader somehow or by overwriting some other method...
Additional information: I am looking for a way to iterate from tuple 1 to tuple n and then again from 1 to n.
Does anyone has an idea how to do something like that?
Thanks!
Sebastian
This is from top of my head, but you could try something like this:
imports here ...;
class MyStorage extends PigStorage {
private int counter = 0;
private Tuple cachedTuple = null;
public Tuple getNext(){
if (this.counter++ % 2 == 0) {
this.cachedTuple = super.getNext();
}
return this.cachedTuple;
}
}
I have a table which has only two column key-value. I want to create a form which allow user insert 3 pair of key-value settings.
Do I need pass 3 different models to the view? Or is there any possible way to do this?
Check out this link:
http://www.yiiframework.com/doc/guide/1.1/en/form.table
This is considered best form in Yii for updating for creating multiple models.
In essence, for creation you can create a for loop generate as many inputs a you wish to have visible, and in your controller loop over the inputs to create new models.
View File:
for ( $settings as $i=>$setting ) //Settings would be an array of Models (new or otherwise)
{
echo CHtml::activeLabelEx($setting, "[$i]key");
echo CHtml::activeLabelEx($setting, "[$i]key");
echo CHtml::error($setting, "[$i]key");
echo CHtml::activeTextField($setting, "[$i]value");
echo CHtml::activeTextField($setting, "[$i]value");
echo CHtml::error($setting, "[$i]value");
}
Controller actionCreate:
$settings = array(new Setting, new Setting, new Setting);
if ( isset( $_POST['Settings'] ) )
foreach ( $settings as $i=>$setting )
if ( isset( $_POST['Setttings'][$i] ) )
{
$setting->attributes = $_POST['Settings'][$i];
$setting->save();
}
//Render View
To update existing models you can use the same method but instead of creating new models you can load models based on the keys in the $_POST['Settings'] array.
To answer your question about passing 3 models to the view, it can be done without passing them, but to validate data and have the correct error messages sent to the view you should pass the three models placed in the array to the view in the array.
Note: The example above should work as is, but does not provide any verification that the models are valid or that they saved correctly
I'm going to give you a heads up and let you know you could potentially make your life very complicated with this.
I'm currently using an EAV patterned table similar to this key-value and here's a list of things you may find difficult or impossible:
use CDbCriteria mergeWith() to filter related elements on "value"s in the event of a search() (or other)
Filtering CGridView or CListView
If this is just very straight forward key-value with no related entity aspect ( which I'm guessing it is since it looks like settings) then one way of doing it would be:
create a normal "Setting" CActiveRecord for your settings table (you will use this to save entries to your settings table)
create a Form model by extending CFormModel and use this as the $model in your form.
Add a save() method to your Form model that would individually insert key-value pairs using the "Setting" model. Preferably using a transaction incase a key-value pair doesn't pass Settings->validate() (if applicable)
optionally you may want to override the Form model's getAttributes() to return db data in the event of a user wanting to edit an entry.
I hope that was clear enough.
Let me give you some basic code setup. Please note that I have not tested this. It should give you a rough idea though.:
Setting Model:
class Setting extends CActiveRecord
{
public function tableName()
{
return 'settings';
}
}
SettingsForm Model:
class SettingsForm extends CFormModel
{
/**
* Load attributes from DB
*/
public function loadAttributes()
{
$settings = Setting::model()->findAll();
$this->setAttributes(CHtml::listData($settings,'key','value'));
}
/*
* Save to database
*/
public function save()
{
foreach($this->attributes as $key => $value)
{
$setting = Setting::model()->find(array('condition'=>'key = :key',
'params'=>array(':key'=>$key)));
if($setting==null)
{
$setting = new Setting;
$setting->key = $key;
}
$setting->value = $value;
if(!$setting->save(false))
return false;
}
return true;
}
}
Controller:
public function actionSettingsForm()
{
$model = new Setting;
$model->loadAttributes();
if(isset($_POST['SettingsForm']))
{
$model->attributes = $_POST['SettingsForm'];
if($model->validate() && $model->save())
{
//success code here, with redirect etc..
}
}
$this->render('form',array('model'=>$model));
}
form view :
$form=$this->beginWidget('CActiveForm', array(
'id'=>'SettingsForm'));
//all your form element here + submit
//(you could loop on model attributes but lets set it up static for now)
//ex:
echo $form->textField($model,'fieldName'); //fieldName = db key
$this->endWidget($form);
If you want further clarification on a point (code etc.) let me know.
PS: for posterity, if other people are wondering about this and EAV they can check the EAV behavior extention or choose a more appropriate DB system such as MongoDb (there are a few extentions out there) or HyperDex
I am trying to load a sortable jqgrid 3.5 from a query with multiple joins in it and having much difficulty as I am a novice with both Linq and jqgrid. In order to allow for sorting I first was attempting to load it using dynamic SQL.
Since I am pulling columns from multiple tables I assume my return will be a class object which I will populate (or will it be a table). How can I return a IQueryable custom class object when using dynamic SQL with multiple .JOIN clauses. If this is impossible how do I return IQueryable data from a stored procedure call. It is easy to create dynamic SQL in the stored procedure - I am unsure how to load my grid with it however.
Sorry if this is all over the place but I can't seem to find a way. If you can recommend the most straight forward way to load my sortable grid from a query which has multiple joins in I am much appreciated.
My controller code:
public ActionResult GridData(string sidx, string sord, int page, int rows)
{
EquipTrak eqt = new EquipTrak();
var equipment = eqt.GetGridEquipment(sidx, sord);
var dataJson = new
{
total = 10000,
page = 1,
records = 10000,
rows = (from e in equipment
select new
{
equip_id = e.equip_id,
cell = new string[] {
e.equip_id,
e.equipType,
e.makeType,
String.Format("{0:MM/dd/yyyy}", e.serv_due_dt)
}
}).ToArray()
};
return Json(dataJson);
}
}
my class code (incomplete):
namespace ULS_Site.Models
{
public class EquipTrak
{
uls_dbDataContext ulsDB = new uls_dbDataContext();
public IQueryable<equipmentCls> GetGridEquipment(string sidx, string sord)
{
try
{
return
Not sure if this is the best or worst solution but I used SQL Server views to handle all the joining required. I could then use .Orderby and .Where against the view which was in my data context.