how to send array of values to a query dynamically in codeigniter - codeigniter

The code in model is
public function get_report6_8($type, $filter_id=NULL) {
$values = array($filter_id);
$select = '';
if ($filter_id && $type == 'jh') {
$select = 'and natbuild_rep.jh_rep_id = ?';
}
else if ($filter_id && $type == 'natbuild') {
$select = 'and natbuild_principal.id = ?';
}
$sql = "select sum(total) total
from (
select value_of_sale total
from lead
left join natbuild_rep
on natbuild_rep.mobile = lead.mobile
left join natbuild_store
on natbuild_store.id = natbuild_rep.store_id
left join natbuild_principal
on natbuild_principal.store_group = ifnull(natbuild_store.store_group2, natbuild_store.store_group)
where (status = 1 OR status = 2)
and value_of_sale is not null
{$select}
group by lead.id
) temp";
return $this->db->query($sql, $values)->row();
}
The code in controller is
$data['report8'] = $this->lead_report_model->get_report6_8($type, $this->input->post('filter'));
code in view is
Grand Total: $total)) ? $report8->total: 0;?>
if I run query like
select sum(total) total
from (
select value_of_sale total
from lead
left join natbuild_rep
on natbuild_rep.mobile = lead.mobile
left join natbuild_store
on natbuild_store.id = natbuild_rep.store_id
left join natbuild_principal
on natbuild_principal.store_group = ifnull(natbuild_store.store_group2, natbuild_store.store_group)
where (status = 1 OR status = 2)
and value_of_sale is not null
and natbuild_principal.id in (18, 30, 31, 35, 33, 25, 23, 15, 8, 6, 5, 29, 7, 3, 2, 1, 24, 27, 22, 21, 20, 26, 36)
group by lead.id ) temp
the result is right. please help how can I send array of values to the $select. This happens when I select grand total from a dropdown which contains all other values up there.

your dropdown is multiselect so it will pass an array with the values.
use
implode(",", $dropdownSelections);
$select = 'and natbuild_principal.id in ('.implode(",", $dropdownSelections).')';

Related

How to Convert this Query to Eloquent or Query Builder?

I have a query like this. How should I convert it into a eloquent or query builder
SELECT
x.MATERIAL_ID,
(SELECT TAPET_NAME FROM MA_TAPE_TYPE WHERE TAPET_CODE = x.MATERIAL_TYPE) as media_type,
(SELECT TAPEF_NAME FROM MA_TAPE_FORMAT WHERE TAPEF_CODE = x.MATERIAL_FORMAT) as media_format,
STOCK_MATERIAL_EPI.HOUSE_NO,
x.TXN_DATE,
STOCK_MATERIAL_EPI.PROGRAM_NAME,
CASE WHEN x.iden_flag = 'P' THEN STOCK_MATERIAL_EPI.epi_title WHEN x.iden_flag = 'C'
THEN STOCK_MATERIAL_EPI.prod_version_name WHEN x.iden_flag = 'M' THEN STOCK_MATERIAL_EPI.promo_name
END as episode_title,
PUR_EPISODE_HDR.EPI_NO,
(SELECT MAX (last_date) FROM run_master WHERE run_master.row_id_epi = PUR_EPISODE_HDR.row_id AND
run_master.run_aired = 'Y') as last_tx,
x.REMARKS,
x.LOCATION_ID as shelf_no,
stock_material_slag.remarks as short_list
FROM STOCK_MATERIAL x
LEFT JOIN STOCK_MATERIAL_EPI ON x.MATERIAL_ID = STOCK_MATERIAL_EPI.MATERIAL_ID
LEFT JOIN stock_material_slag ON x.MATERIAL_ID = stock_material_slag.MATERIAL_ID
LEFT JOIN PUR_EPISODE_HDR ON STOCK_MATERIAL_EPI.ROW_ID_EPI = PUR_EPISODE_HDR.ROW_ID
I'm confused as to how to convert them. Can someone help me.
I tried to write like this.
But it doesn't work,
$materials = DB::connection('oracle')
->table('STOCK_MATERIAL AS x')
->select('x.MATERIAL_ID',
DB::raw("(SELECT TAPET_NAME FROM MA_TAPE_TYPE WHERE TAPET_CODE = x.MATERIAL_TYPE) as MEDIA_TYPE"),
DB::raw("(SELECT TAPEF_NAME FROM MA_TAPE_FORMAT WHERE TAPEF_CODE = x.MATERIAL_FORMAT) as MEDIA_FORMAT"),
'x.TXN_DATE',
'y.HOUSE_NO', 'y.PROGRAM_NAME',
DB::raw("(CASE WHEN x.IDEN_FLAG = 'P' THEN z.EPI_TITLE WHEN x.IDEN_FLAG = 'C' THEN z.PROD_VERSION_NAME WHEN x.IDEN_FLAG = 'M' THEN z.PROMO_NAME END as EPISODE_TITLE)"),
'w.EPI_NO',
DB::raw("(SELECT MAX (LAST_DATE) FROM RUN_MASTER WHERE RUN_MASTER.ROW_ID_EPI = w.ROW_ID AND RUN_MASTER.RUN_AIRED = 'Y') as LAST_TX"),
'z.REMARKS',
'x.LOCATION_ID as SHELF_NO',
'z.REMARKS'
)
->leftJoin('STOCK_MATERIAL_EPI AS y', 'y.MATERIAL_ID', '=', 'x.MATERIAL_ID')
->leftJoin('STOCK_MATERIAL_SLAG AS z', 'z.MATERIAL_ID', '=', 'x.MATERIAL_ID')
->leftJoin('PUR_EPISODE_HDR AS w', 'w.ROW_ID', '=', 'y.ROW_ID_EPI')
What else do I write right?
You would need to define eloquent models and then use with(). Documentation can be found at the link below: https://laravel.com/docs/7.x/eloquent-relationships#constraining-eager-loads
example
StockMaterial::with([
'maTapeType' => function($query) {
$query->get('name')
})
])
For Query Builder you DB::raw and DB::leftJoin to create the same query.
DB::from('STOCK_MATERIAL')
->selectRaw([
'TAPET_NAME as media_type',
'CASE WHEN x.iden_flag = "P" THEN STOCK_MATERIAL_EPI.epi_title
WHEN x.iden_flag = "C" THEN STOCK_MATERIAL_EPI.prod_version_name
WHEN x.iden_flag = "M" THEN STOCK_MATERIAL_EPI.promo_name
END as episode_title',
])
->leftJoin('MA_TAPE_TYPE', 'TAPET_CODE', 'STOCK_MATERIAL.MATERIAL_TYPE')
https://laravel.com/docs/7.x/queries#raw-expressions
https://laravel.com/docs/7.x/queries#joins

Is there a solution to this formula stopping an AutoSort script

I am attempting to learn to script as I develop a project so please forgive me if I ask this question incorrectly.
I have created an AutoSort script for a google sheets document to sort a list of players by "Weight". It works fine until I add the following formula. Once I add this formula, my data is to be sorted by Column 7, largest to smallest and doesn't completely. The odd part of this is that the players that are out of order are listed as Substitutes.
The way this sheet works.
The Match Tool tab is where players are selected from Data Validation cells.
The Data Validation list comes from the MR1 Tab.
The MR1 tab gets it list based on an importrange defined in the MRTool.
This comes from a larger document and I've extracted the vital parts to make the error happen. I've tried to run a bare-bones version with only text and the AutoSort script and it sorts correctly. I have also tried changing which column the AutoSort looks in and it works correctly.
The formula that stops the script from working:
=if(or(C10="",C10=". Blank"),"",iferror(index('MR1'!$B$8:$H$87,(match(C10,'MR1'!$N$8:$N$87,0))),"Player Not Found"))
The Script for the AutoSort:
var roster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Match Tool");
var range1 = roster.getRange("B10:K59");
var range2 = roster.getRange("N10:W59");
range1.sort( [{ column : 7, ascending: false}, { column : 11, ascending: false}] );
range2.sort( [{ column : 19, ascending: false}, { column : 23, ascending: false}] );
}
function SortLeft() {
var roster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Match Tool");
var range1 = roster.getRange("B10:K59");
range1.sort( [{ column : 7, ascending: false}, { column : 11, ascending: false}] );
}
function SortRight() {
var roster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Match Tool");
var range2 = roster.getRange("N10:W59");
// It seems that column numbers are always sequential from the first one, even if you are addressing a range. Hence using 14/18 here instead of 4/8
range2.sort( [{ column : 19, ascending: false}, { column : 23, ascending: false}] );
}
function SortSelection() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getActiveRange();
var firstcol = range.getColumn();
var lastcol = range.getLastColumn();
//Before sorting, this code checks to make sure that Clan through Combined heroes is selected on one side or the other. If not, an error appears.
if (firstcol == 2 && lastcol == 11 ) { range.sort( [{ column : 7, ascending: false}, { column : 11, ascending: false}] )} //&& lastcol == 11
else if ( firstcol == 14 && lastcol == 23 ) { range.sort( [{ column : 19, ascending: false}, { column : 23, ascending: false}] )} //&& lastcol == 23
else { SpreadsheetApp.getUi().alert('You can only sort selections that include all 8 data columns, from Clan to Notes.');}
}
function onEdit(e){
var roster = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Match Tool");
var autosort = roster.getRange(6, 13).getValue();
var range1 = roster.getRange("B10:K59");
var range2 = roster.getRange("N10:W59");
// if('B3' === GWL) {
// SpreadsheetApp.getActiveSheet().getRange('K2').setValue('40');
// }
// test if K2 (war size) was modified
if (e.source.getActiveSheet().getName() == "Match Tool" && e.range.rowStart === 6 && e.range.columnStart === 13) {
moveToSub();
}
//preform autosort if on
if ( autosort == "On" ){
range1.sort( [{ column : 7, ascending: false}, { column : 11, ascending: false}] );
range2.sort( [{ column : 19, ascending: false}, { column : 23, ascending: false}] );
}
}
I expect players to be sorted by column 7 (column G) descending and then column 11 (Column K) descending. What I'm getting is certain players not sorted correctly.
I am getting - 132, 131, 131, 113, 111, 132, 113, 90, 88, 87, 86.
I should see - 132, 132, 131, 131, 113, 113, 111, 90, 88, 87, 86.
Thank you for taking the time to help me.
After some help from a friend, we realized the problem wasn't anything to do with the script on this page, it was how the data was entered on the sheet the data was imported in from. Some numbers were entered as numerals while others were entered in as text. By changing the text to numerals, the script performed as expected.
So the moral of the story is, check to make sure the data being sort is of the same type.

how to display data in a table column using fpdf

My piece of code is:
for ( $i=2060; $i< $FINAL; $i++ ) {
$pdf->Cell( 36, 12, ( '05/' .number_format( $dataRow[$i] ) ), 1, 0, 'C', $fill );
}
expected pdf output as a column of cells using fpdf is:
05/2060
05/2061
05/2062
05/2063
05/2064
please guide me how to get the above desirable output.
Try adding 1 on the ln part instead of 0
for ( $i=2060; $i< $FINAL; $i++ ) {
$pdf->Cell( 36, 12, ( '05/' .number_format( $dataRow[$i] ) ), 1, 1, 'C', $fill );
}
and make sure that $FINAL has a value and you can do '05/'.$i also, and $fill must be true or false

LINQ and 2 datatables

I have 2 datatables in a dataset. One table has a list called CostTypes. Just an Id and Description field.
The other datatable is the master table and has many records and one of the columns is the cost type. There will be cost types that are not reference in this datatable. There is another column in this databale called cost.
What I am trying to do is get a summary by cost type with a total of the cost. But I want ALL cost types listed any values not in the master table will be zero.
CostType table
Id, Description
1,Marketing
2,Sales
3,Production
4,Service
Master table
Id, Cost, CostTypeId
1,10,1
2,120,1
3,40,3
So I would like to see a result in a datable (if possible) so I can bind to datagridview
Marketing 130
Sales 0
Production 40
Service 0
Thanks for the help everyone, this is what I came up from the answers - Can anyone suggest any improvements???
Also how can I convert the result in query1 into a datable???
var query1 =
from rowCT in costTypes.AsEnumerable()
from rowSTD in stdRates.AsEnumerable()
.Where( d => d.Field<int?>( "CostTypeId" ) == rowCT.Field<int?>( "CostTypeId" ) )
.DefaultIfEmpty()
group new { row0 = rowCT, row1 = rowSTD }
by rowCT.Field<string>( "Description" ) into g
select new
{
g.Key,
Cost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "Cost" ) ),
TotalCost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalCost" ) ),
TotalHours = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalHours" ) ),
TotalLabourCost = g.Sum( x => x.row1 == null ? 0 : x.row1.Field<decimal>( "TotalLabourCost" ) )
}
;
Maybe something like this:
Test data:
DataTable dt=new DataTable();
dt.Columns.Add("Id",typeof(int));
dt.Columns.Add("Description",typeof(string));
dt.Rows.Add(1,"Marketing");
dt.Rows.Add(2,"Sales");
dt.Rows.Add(3,"Production");
dt.Rows.Add(4,"Service");
DataTable dt2=new DataTable();
dt2.Columns.Add("Id",typeof(int));
dt2.Columns.Add("Cost",typeof(int));
dt2.Columns.Add("CostTypeId",typeof(int));
dt2.Rows.Add(1,10,1);
dt2.Rows.Add(2,120,1);
dt2.Rows.Add(3,40,1);
Linq query
var query=(
from row in dt.AsEnumerable()
from row1 in dt2.AsEnumerable()
.Where (d =>d.Field<int>("Id")==row.Field<int>("Id") )
.DefaultIfEmpty()
group new{row,row1}
by row.Field<string>("Description") into g
select new
{
g.Key,
Cost=g.Sum (x =>x.row1==null?0:x.row1.Field<int>("Cost"))
}
);
Result
Key Cost
Marketing 10
Sales 120
Production 40
Service 0
You can use the Sum extension method to compute the cost. It will return 0 if the collection is empty which is exactly what you want:
var costTypes = new DataTable("CostTypes");
costTypes.Columns.Add("Id", typeof(Int32));
costTypes.Columns.Add("Description", typeof(String));
costTypes.Rows.Add(1, "Marketing");
costTypes.Rows.Add(2, "Sales");
costTypes.Rows.Add(3, "Production");
costTypes.Rows.Add(4, "Service");
var costEntries = new DataTable("CostEntries");
costEntries.Columns.Add("Id", typeof(Int32));
costEntries.Columns.Add("Cost", typeof(Int32));
costEntries.Columns.Add("CostTypeId", typeof(Int32));
costEntries.Rows.Add(1, 10, 1);
costEntries.Rows.Add(2, 120, 1);
costEntries.Rows.Add(3, 40, 3);
var costs = costTypes
.Rows
.Cast<DataRow>()
.Select(
dr => new {
Id = dr.Field<Int32>("Id"),
Description = dr.Field<String>("Description")
}
)
.Select(
ct => new {
ct.Description,
TotalCost = costEntries
.Rows
.Cast<DataRow>()
.Where(ce => ce.Field<Int32>("CostTypeId") == ct.Id)
.Sum(ce => ce.Field<Int32>("Cost"))
}
);
The result is:
Description|TotalCost
-----------+---------
Marketing | 130
Sales | 0
Production | 40
Service | 0
You can create a new DataSet quite simply:
var costsDataTable = new DataTable("Costs");
costsDataTable.Columns.Add("Description", typeof(String));
costsDataTable.Columns.Add("TotalCost", typeof(Int32));
foreach (var cost in costs)
costsDataTable.Rows.Add(cost.Description, cost.TotalCost);
If the linear search performed by the Where in the code above is a concern you can improve the performance by creating a lookup table in advance:
var costEntriesLookup = costEntries
.Rows
.Cast<DataRow>()
.Select(
ce => new {
Cost = ce.Field<Int32>("Cost"),
CostTypeId = ce.Field<Int32>("CostTypeId")
}
)
.ToLookup(ce => ce.CostTypeId, ce => ce.Cost);
var costs = costTypes
.Rows
.Cast<DataRow>()
.Select(
dr => new {
Id = dr.Field<Int32>("Id"),
Description = dr.Field<String>("Description")
}
)
.Select(
ct => new {
ct.Description,
TotalCost = costEntriesLookup.Contains(ct.Id)
? costEntriesLookup[ct.Id].Sum()
: 0
}
);
I came up with a simpler bit of linq than others seemed to use. Thanks to Martin Liversage for the code to create the input data.
var costTypes = new DataTable("CostTypes");
costTypes.Columns.Add("Id", typeof(Int32));
costTypes.Columns.Add("Description", typeof(String));
costTypes.Rows.Add(1, "Marketing");
costTypes.Rows.Add(2, "Sales");
costTypes.Rows.Add(3, "Production");
costTypes.Rows.Add(4, "Service");
var costEntries = new DataTable("CostEntries");
costEntries.Columns.Add("Id", typeof(Int32));
costEntries.Columns.Add("Cost", typeof(Int32));
costEntries.Columns.Add("CostTypeId", typeof(Int32));
costEntries.Rows.Add(1, 10, 1);
costEntries.Rows.Add(2, 120, 1);
costEntries.Rows.Add(3, 40, 3);
var cte = costTypes.Rows.Cast<DataRow>();
var cee = costEntries.Rows.Cast<DataRow>();
var output = cte.Select(
ct => new {
Description = ct["Description"],
Sum = cee.Where(ce=>ce["CostTypeId"].Equals(ct["Id"])).Sum(ce=>(int)ce["Cost"])
}
);
This may lose efficiency on larger tables since each cost type will search the cost entry table whereas using grouping I suspect you only need one pass over the table. Personally I'd prefer the (to my mind) simpler looking code. It will depend on your use case though.

LINQ Where with AND OR condition

So I have managed to get this query working
List<string> listStatus = new List<string>() ;
listStatus.add("Text1");
List<string> listMerchants = new List<string>() ;
listMerchants.add("Text2");
from item in db.vw_Dropship_OrderItems
where listStatus.Contains(item.StatusCode)
&& listMerchants.Contains(item.MerchantId)
select item;
Here I would like to check if listStatus and listMerchants are not null only then put them inside WHERE clause.
Like
if listMerchants is null then query will be like
where listStatus.Contains(item.StatusCode)
I do not want to use switch or If condition.
Thanks
from item in db.vw_Dropship_OrderItems
where (listStatus != null ? listStatus.Contains(item.StatusCode) : true) &&
(listMerchants != null ? listMerchants.Contains(item.MerchantId) : true)
select item;
Might give strange behavior if both listMerchants and listStatus are both null.
Well, you're going to have to check for null somewhere. You could do something like this:
from item in db.vw_Dropship_OrderItems
where (listStatus == null || listStatus.Contains(item.StatusCode))
&& (listMerchants == null || listMerchants.Contains(item.MerchantId))
select item;
Linq With Or Condition by using Lambda expression you can do as below
DataTable dtEmp = new DataTable();
dtEmp.Columns.Add("EmpID", typeof(int));
dtEmp.Columns.Add("EmpName", typeof(string));
dtEmp.Columns.Add("Sal", typeof(decimal));
dtEmp.Columns.Add("JoinDate", typeof(DateTime));
dtEmp.Columns.Add("DeptNo", typeof(int));
dtEmp.Rows.Add(1, "Rihan", 10000, new DateTime(2001, 2, 1), 10);
dtEmp.Rows.Add(2, "Shafi", 20000, new DateTime(2000, 3, 1), 10);
dtEmp.Rows.Add(3, "Ajaml", 25000, new DateTime(2010, 6, 1), 10);
dtEmp.Rows.Add(4, "Rasool", 45000, new DateTime(2003, 8, 1), 20);
dtEmp.Rows.Add(5, "Masthan", 22000, new DateTime(2001, 3, 1), 20);
var res2 = dtEmp.AsEnumerable().Where(emp => emp.Field<int>("EmpID")
== 1 || emp.Field<int>("EmpID") == 2);
foreach (DataRow row in res2)
{
Label2.Text += "Emplyee ID: " + row[0] + " & Emplyee Name: " + row[1] + ", ";
}

Resources