Create table based on the data value of another table in Laravel - laravel

I try to create a new table based on the existing table. If the table value in A = 'TC' or '0', the table value in B will be '0', else the table value in B will follow the table value in A.
This is what I have tried, but I'm not sure about the logic that I code. Hopefully, someone will help me.
$subject = Scsj::get();
if ($subject->teknologi_dan_sistem_maklumat=='TC'||'0') {
$subject->teknologi_dan_sistem_maklumat=='0';
} else {
$subject->teknologi_dan_sistem_maklumat=='1';
}

First of all, you use the equal operator to set the variable. As 1000Nettles said, get() will return you a collection of data. If you wish to retreive an object, use the first() method.
Besides, I would rewrite your code to make it smaller:
$subject = Scsj::first();
$var = $subject->teknologi_dan_sistem_maklumat;
if ($var =='TC'|| $var == '0') {
$subject->teknologi_dan_sistem_maklumat = '0';
} else {
$subject->teknologi_dan_sistem_maklumat = '1';
}
Edit:
You are trying to make a new database record, setting the value of the old database record wont help unless you plan on updating the record.

Related

Is there any better way to check if the same data is present in a table in .Net core 3.1?

I'm pulling data from a third party api. The api runs multiple times in a day. So, if the same data is present in the table it should ignore that record, else if there are any changes it should update that record or insert a new record if anything new shows up in the json received.
I'm using the below code for inserting any new data.
var input = JsonConvert.DeserializeObject<List<DeserializeLookup>>(resultJson).ToList();
var entryset = input.Select(y => new Lookup
{
lookupType = "JOBCODE",
code = y.Code,
description = y.Description,
isNew = true,
lastUpdatedDate = DateTime.UtcNow
}).ToList();
await _context.Lookup.AddRangeAsync(entryset);
await _context.SaveChangesAsync();
But, after the first run, when the api runs again it's again inserting the same data in the table. As a result, duplicate entries are getting into table. To handle the same, I used a foreach loop as below before inserting data to the table.
foreach (var item in input)
{
if (!_context.Lookup.Any(r =>
r.code== item.Code))
{
//above insert code
}
}
But, the same doesn't work as expected. Also, the api takes a lot of time to run when I put a foreach loop. Is there a solution to this in .net core 3.1
List<DeserializeLookup> newList=new();
foreach (var item in input)
{
if (!_context.Lookup.Any(r =>
r.code== item.Code))
{
newList.add(item);
//above insert code
}
}
await _context.Lookup.AddRangeAsync(newList);
await _context.SaveChangesAsync();
It will be better if you try this way
I’m on my phone so forgive me for not being able to format the code in my response. The solution to your problem is something I actually just encountered myself while syncing data from an azure function and third party app and into a sql database.
Depending on your table schema, you would need one column with a unique identifier. Make this column a primary key (first step to preventing duplicates). Here’s a resource for that: https://www.w3schools.com/sql/sql_primarykey.ASP
The next step you want to take care of is your stored procedure. You’ll need to perform what’s commonly referred to as an UPSERT. To do this you’ll need to merge a table with the incoming data...on a specified column (whichever is your primary key).
That would look something like this:
MERGE
Table_1 AS T1
USING
Incoming_Data AS source
ON
T1.column1 = source.column1
/// you can use an AND / OR operator in here for matching on additional values or combinations
WHEN MATCHED THEN
UPDATE SET T1.column2= source.column2
//// etc for more columns
WHEN NOT MATCHED THEN
INSERT (column1, column2, column3) VALUES (source.column1, source.column2, source.column3);
First of all, you should decouple the format in which you get your data from your actual data handling. In your case: get rid of the JSon before you actually interpret the data.
Alas, I haven't got a clue what your data represents, so Let's assume your data is a sequence of Customer Orders. When you get new data, you want to Add all new orders, and you want to update changed orders.
So somewhere you have a method with input your json data, and as output a sequence of Orders:
IEnumerable<Order> InterpretJsonData(string jsonData)
{
...
}
You know Json better than I do, besides this conversion is a bit beside your question.
You wrote:
So, if the same data is present in the table it should ignore that record, else if there are any changes it should update that record or insert a new record
You need an Equality Comparer
To detect whether there are Added or Changed Customer Orders, you need something to detect whether Order A equals Order B. There must be at least one unique field by which you can identify an Order, even if all other values are of the Order are changed.
This unique value is usually called the primary key, or the Id. I assume your Orders have an Id.
So if your new Order data contains an Id that was not available before, then you are certain that the Order was Added.
If your new Order data has an Id that was already in previously processed Orders, then you have to check the other values to detect whether it was changed.
For this you need Equality comparers: one that says that two Orders are equal if they have the same Id, and one that says checks all values for equality.
A standard pattern is to derive your comparer from class EqualityComparer<Order>
class OrderComparer : EqualityComparer<Order>
{
public static IEqualityComparer<Order> ByValue = new OrderComparer();
... // TODO implement
}
Fist I'll show you how to use this to detect additions and changes, then I'll show you how to implement it.
Somewhere you have access to the already processed Orders:
IEnumerable<Order> GetProcessedOrders() {...}
var jsondata = FetchNewJsonOrderData();
// convert the jsonData into a sequence of Orders
IEnumerable<Order> orders = this.InterpretJsonData(jsondata);
To detect which Orders are added or changed, you could make a Dictonary of the already Processed orders and check the orders one-by-one if they are changed:
IEqualityComparer<Order> comparer = OrderComparer.ByValue;
Dictionary<int, Order> processedOrders = this.GetProcessedOrders()
.ToDictionary(order => order.Id);
foreach (Order order in Orders)
{
if(processedOrders.TryGetValue(order.Id, out Order originalOrder)
{
// order already existed. Is it changed?
if(!comparer.Equals(order, originalOrder))
{
// unequal!
this.ProcessChangedOrder(order);
// remember the changed values of this Order
processedOrder[order.Id] = Order;
}
// else: no changes, nothing to do
}
else
{
// Added!
this.ProcessAddedOrder(order);
processedOrder.Add(order.Id, order);
}
}
Immediately after Processing the changed / added order, I remember the new value, because the same Order might be changed again.
If you want this in a LINQ fashion, you have to GroupJoin the Orders with the ProcessedOrders, to get "Orders with their zero or more Previously processed Orders" (there will probably be zero or one Previously processed order).
var ordersWithTPreviouslyProcessedOrder = orders.GroupJoin(this.GetProcessedOrders(),
order => order.Id, // from every Order take the Id
processedOrder => processedOrder.Id, // from every previously processed Order take the Id
// parameter resultSelector: from every Order, with its zero or more previously
// processed Orders make one new:
(order, previouslyProcessedOrders) => new
{
Order = order,
ProcessedOrder = previouslyProcessedOrders.FirstOrDefault(),
})
.ToList();
I use GroupJoin instead of Join, because this way I also get the "Orders that have no previously processed orders" (= new orders). If you would use a simple Join, you would not get them.
I do a ToList, so that in the next statements the group join is not done twice:
var addedOrders = ordersWithTPreviouslyProcessedOrder
.Where(orderCombi => orderCombi.ProcessedOrder == null);
var changedOrders = ordersWithTPreviouslyProcessedOrder
.Where(orderCombi => !comparer.Equals(orderCombi.Order, orderCombi.PreviousOrder);
Implementation of "Compare by Value"
// equal if all values equal
protected override bool Equals(bool x, bool y)
{
if (x == null) return y == null; // true if both null, false if x null but y not null
if (y == null) return false; // because x not null
if (Object.ReferenceEquals(x, y) return true;
if (x.GetType() != y.GetType()) return false;
// compare all properties one by one:
return x.Id == y.Id
&& x.Date == y.Date
&& ...
}
For GetHashCode is one rule: if X equals Y then they must have the same hash code. If not equal, then there is no rule, but it is more efficient for lookups if they have different hash codes. Make a tradeoff between calculation speed and hash code uniqueness.
In this case: If two Orders are equal, then I am certain that they have the same Id. For speed I don't check the other properties.
protected override int GetHashCode(Order x)
{
if (x == null)
return 34339d98; // just a hash code for all null Orders
else
return x.Id.GetHashCode();
}

Update a database field with Joomla UpdateObject method with a calculated field from same table

Right to the point.
I need to update a field in the database using the field to calculate the new value first.
E.g of fields: https://i.stack.imgur.com/FADH6.jpg
Now I am using the Joomla updateObject function. my goal is to take the "spent" value from the DB table without using a select statement.
Then I need to calculate a new value with it like (spent + 10.00) and update the field with the new value. Check out the code below:
// Create an object for the record we are going to update.
$object = new stdClass();
// Must be a valid primary key value.
$object->catid = $item['category'];
$object->spent = ($object->spent - $item['total']);
// Update their details in the users table using id as the primary key.
$result = JFactory::getDbo()->updateObject('#__mytable', $object, 'catid');
The bit which i need to make the calculation on is
$object->spent = ($object->spent - $item['total']);
I realise I can use a seperate insert statement but I am wondering if there is a better way. Any help is much appreciated.
It needs to work like this, WITHOUT THE SELECT (working example)
$query = $db->getQuery(true);
$query->select($db->quoteName('spent'));
$query->from($db->quoteName('#__mytable'));
$query->where($db->quoteName('catid')." = ". $item['category']);
// Reset the query using our newly populated query object.
$db->setQuery($query);
$oldspent = $db->loadResult();
// Create an object for the record we are going to update.
$object = new stdClass();
// Must be a valid primary key value.
$object->catid = $item['category'];
$object->spent = ($oldspent - $item['total']);
// Update their details in the users table using id as the primary key.
$result = JFactory::getDbo()->updateObject('#__mytable', $object, 'catid');
The sticking point with trying to use updateObject('#__mytable', $object, 'catid'); is that your query logic needs to reference the column name in the calculation to assign the "difference" as the new value. The raw mysql query syntax to update a column value with the value minus another value is like:
"`spent` = `spent` - {$item['total']}"
updateObject() will convert spent - {$item['total']} to a literal string, the database will expect a numeric value, so UPDATE results in a 0 value recorded. In other words, $db->getAffectedRows() will give you a positive count and there will be no errors generated, but you don't get the desired mathematical action.
The workaround is to discard updateObject() as a tool and build an UPDATE query without objects -- don't worry it's not too convoluted. I'll build in some diagnostics and failure checking, but you can remove whatever parts that you wish.
I have tested the following code to be successful on my localhost:
$db = JFactory::getDBO();
try {
$query = $db->getQuery(true)
->update($db->quoteName('#__mytable'))
->set($db->quoteName("price") . " = " . $db->qn("price") . " - " . (int)$item['total'])
->where($db->quoteName("catid") . " = " . (int)$item['category']);
echo $query->dump(); // see the generated query (but don't show to public)
$db->setQuery($query);
$db->execute();
if ($affrows = $db->getAffectedRows()) {
JFactory::getApplication()->enqueueMessage("Updated. Affected Rows: $affrows", 'success');
} else {
JFactory::getApplication()->enqueueMessage("Logic Error", 'error');
}
} catch (Exception $e) {
JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error'); // never show getMessage() to public
}
Here is a StackOverflow page discussing the mysql subtraction logic: update a column by subtracting a value

LINQ statement with conditional selection from table

I am new to linq so I apologize in advance if it a dumb question. I inherited the following query and it is not producing correct results in order to fix it I have to understand what it is doing.
Here is the query, if someone can explain it to me what it is doing (also possibly fix it) that will be greatly appreciated.
**using (var dbCtx = new TLMDbContext())
{
var dvps = dbCtx.tblDVPTests.Where(x => x.DVPID == 2176);
// these 2 following if conditions doesnt bring correct result sets
if (dvpMasterPhaseId.HasValue)
{
dvps = dvps.Where(x => x.tblDVPPhases.All(p => p.DVPMasterPhaseID ==255));
}
if (dvpMasterVariantId.HasValue)
{
dvps = dvps.Where(x => x.tblDVPPhases.All(p => p.tblDVPVariants.All(v=>v.DVPMasterVariantID==681)));
}
}**
UPDATE
I want this following query to be written in LINQ and if one of you guys tell me what was wrong with the LINQ query above that will be great.
select * from tblDVPTest
inner join tblDVPPhase on tblDVPTest.DVPTestID=tblDVPPhase.DVPTestID
where dvpid=2176 and tblDVPPhase.DVPMasterPhaseID=255
Here is with both condition
select * from tblDVPTest
inner join tblDVPPhase on tblDVPTest.DVPTestID=tblDVPPhase.DVPTestID
inner join tblDVPVariant on tblDVPPhase.DVPPhaseID=tblDVPVariant.DVPPhaseID
where dvpid=2176 and tblDVPPhase.DVPMasterPhaseID=255 and tblDVPVariant.DVPMasterVariantID=681
As I can understand from code, you are using entity framework to interact with database. Below is a high level explanation:
Create DbContext object.
Select everything from table tblDVPTests into variable dvps where column DVPID of table tblDVPTests matches value of variable dvpNum.
If nullable variable dvpMasterPhaseId is not null then select only those values from dvps where referenced table tblDVPPhases has all rows with column DVPMasterPhaseID value matching with variable dvpMasterPhaseId value. Store result in dvps. If variable dvpMasterPhaseId is null skip this step.
If nullable variable dvpMasterVariantId is not null then select only those values from dvps where referenced table tblDVPPhases has all rows with column DVPMasterVariantID value matching with variable dvpMasterVariantId value. Store result in dvps. If variable dvpMasterVariantId is null skip this step.
Dispose DbCOntext object.
Note: There is a foreign key relationship between table tblDVPTests and tblDVPPhases.
To fix your issue first of all you should let us know what exactly you are expecting in the result.

How to fetch data for multiple values of a parameter one by one

I have multiple values for one parameter i want to fetch data for each query for every value of parameter in Birt report. i'm getting data only for one value of parameter not all. m using Scripted data source.Open and fetch methods.Thanks
Open in DataSet
importPackage(Packages.com.abc.test.events);
var TlantNo = params["tlant"].value;
var reqNo = params["Number"].value;
poreEvents = new StdPoreReqEvents();
poreEvents.setReqNo(reqNo);
poreEvents.setTlantNo(TlantNo);
poreEvents.open();
fetch
var poreRO = poreEvents.fetch();
if (poreRO == null) {
return false;
} else
{
row["REQ_NO"] = poreRO.getReqNo();
row["REQ_DATE"] = poreRO.getReqDate();
return true;
}
A report parameter with multiple values is an array, we have to iterate on it through the scripted dataset.
In open event of the dataset, we only have to initialize a global index:
i=0;
In fetch event, process each iteration with something such the script below. Pay a special attention how we get the value of reqNo:
importPackage(Packages.com.abc.test.events);
if (params["Number"].value!=null && i<params["Number"].value.length){
var TlantNo = params["tlant"].value;
var reqNo = params["Number"].value[i];
//ETC. do here your stuff with porevents, declare poreRO, check if result is null
row["REQ_NO"] = poreRO.getReqNo();
row["REQ_DATE"] = poreRO.getReqDate();
i++; //Important: increment this even if poreRO is null, otherwise infinite loop
return true; //should return true even if poreRO was null, to process next rows
}else{
return false;
}
The other approach is to do this problem is by defining a dataset having output column which is the multiple value parameter Fetch that column by IN query of the multiple value parameter then pass that value means(output column value) to the other datasets as a Input/output parameter and give binding to parameter.
It resolved my problem :)

How do I check whether a value in a query result is null or not? - Active Record - CodeIgniter

I wanted to know how to check whether there is a value present in a table (managers) and then add a 'yes' or 'no' string depending on if there is a value in that table or not.
$this->db->select('employees.first_name, employees.last_name, departments.department_name, departments.department_numb, titles.title');
$this->db->from('employees');
$this->db->where('first_name', $firstname);
$this->db->where('last_name', $lastname);
$this->db->join('department_manager', 'department_manager.emp_numb = employees.emp_numb', 'inner');
$this->db->join('departments', 'departments.department_numb = department_manager.department_numb', 'inner');
$this->db->join('titles', 'titles.emp_numb = employees.emp_numb', 'inner');
$this->db->where('department_name', $dept);
$this->db->where('title', $jobtitle);
$result = $this->db->get();
$data = array();
foreach($result->result() as $row)
{
$entry = array();
$entry['firstname'] = $row->first_name;
$entry['lastname'] = $row->last_name;
$entry['jobtitle'] = $row->title;
$entry['dept'] = $row->department_name;
$entry['deptid'] = $row->department_number;
//$entry['ismanager'] =
$data[] = $entry;
}
return $data;
I want to check whether an employee is present in the table 'department_manager' which is joined by an employees number. So if that employee number is not present in the table 'department_manager' then I want to insert in the array index $entry[ismanager'] a string which says 'no', and if the employee number is present in the table 'department_manager' then I want $entry['ismanager'] to hold the string 'yes'.
But I'm confused as to how to check that the employee is present or not in that table. Do I do it in the active record query or in the foreach loop? And if it is done in the foreach loop then how do I make that comparison as the query is completed?
Why have a field that is basically a calculated value? That's like having fields for quantity per box, quantity of boxes then saving the total items to a third field. Never save to the database something you can gain access to via a quick query. In your query above it's as simple as changing the dept manager join to a left join, including the dept manager id and saying if that field is blank in a record the person is not a manager. Using a LEFT join will return all records whether they have an entry in the management table or not.
Add: department_manager.emp_numb to the select.
The Join:
$this->db->join('department_manager', 'department_manager.emp_numb
= employees.emp_numb', 'left');
Then in the foreach:
if(!$row->department_manager.emp_numb)
{
this person is not a manager;
}
If you feel you really must have that extra field then you can still populate it with the method above.
If you are using MySQL, I think you are looking for:
IFNULL(expr1,expr2)
where:
expr1 == null condition (in your case NULL)
expr2 == replacement value
Source: Control Flow Functions

Resources