NodeJS mysql fetching related data - mysql

In my database I have two tables. Let's call them A and B. B table has foreign keys related to ids of records in A table.
I fetch couple of ids from A table and I want to find records in B table with foreign keys matching to those ids. However not every record in A table has records related to it in B table.
So in my code it looks like this:
var idsFromA = [1, 2, 3, 4, 5]
connection.query("SELECT * FROM B_table WHERE a_id = ?", idsFromA, function(err, results) {
if (err) {
return console.log(err)
} else {
// always empty
console.log(results);
}
});
Let's say ids number 1 and 2 from table A has record related to them in table B. Rest of them not. I want to get records from table B with those foreign keys but I receive only an empty array. It works only if I type query with only one matching value. But for the whole array of values where some of them don't have related record not.
How can I fix it and get information about those record?

Instead of = you have to use IN and you need to pass the array as value for the first placeholder.
connection.query("SELECT * FROM B_table WHERE a_id IN (?)", [idsFromA], ...)
The way you wrote it only the first id in the array idsFromA would be used for the ?.
Instead of using two queries you might want to use a LEFT JOIN, and the nestTables option.
connection.query({
query: 'SELECT * FROM A_table LEFT JOIN B_table ON (A_table.id=B_table.a_id) WHERE ...some condition to filter A...',
nestTables: true
}, function(err, results) {
if (err) {
console.log(err)
} else {
console.dir(results);
}
});

Related

How to make where condition always be true with field =?

I have a sql statement follow:
select * from table where id = ?
Now, problem is, l don't know whether front end will send me the value of id, if it did, this sql seem like id = 1, and if not, sql should be like id = true(fake code) to find all data
How could I write my sql?
Or, It is fundamentally wrong?
This is normally handled by using logic such as this:
select *
from table
where id = ? or ? is null;
If you don't want to pass the parameter twice or use named parameters:
select t.*
from table t cross join
(select ? as param) params
where id = params.param or params.param is null;
If you want to return all ids if the passed-in value does not exist:
select t.*
from table t
where id = ? or
not exists (select 1 from table t2 where t2.id = ?);
What you can try doing is in your code, write a function for fetching a specific record, and another function for fetching all the records from your table.
In PHP, it could be something like:
// Fetching a specific record
function getCustomerRecord($customerId) {
// Code to fetch specific record from database
}
// Fetching all records
function getAllCustomerRecords() {
// Code to fetch all records from database
}
In the function where you process requests received, check first if a value for id was passed. If a value for id was passed, call the function to fetch a specific record, making sure to pass along the value you received as an argument. Otherwise, call the function to fetch all the records from your table.
You can try doing this to get your right sql statement in PHP
function GetSqlStatement($id){
return $sql = "select * from table where id = ".$id.";";
}

Filter Table, based on field in another table

I'm stumped with this. I have a table with various fields:
$employees. This, I guess, is what you call a collection, I think, that when I call, returns all employee records in the database (4 records in this example)
Each employee record has the following fields
first_name, last_name, age, other_id
There is another table (or collection), which I'm calling filter table. It is called $other_ids. This has two records, with the following fields - id, id_name.
I want to be able to filter the $employees table so that it only keeps the records, where other_id is equal to one of the two values of id in the filter table- $other_ids
So for example, if the filter table has the following two records:
[{"id":1 "id_name":"one"}, {"id":2, "id_name":"two"}]
And the $employee table contains the records:
[{"first_name":"ted", "surname_name":"stark", "age":35, "other_id":1},
{"first_name":"fred", "surname_name":"strange", "age":30, "other_id":2},
{"first_name":"incredible", "surname_name":"hulk", "age":25, "other_id":3},
{"first_name":"captain", "surname_name":"stone", "age":28, "other_id":2}]
After, the filtering, it should return $employees_filtered should only have records 1, 2, and 4
I've tried doing left-join and using whereHas, and where clauses, but nothing works!
I think you are looking for something like -
$otherId = [1, 2];
$employees_filtered = Employee::with('Others')->whereIn('other_id', $otherId)->get();
Please don't forget to make a relationship with their model.
In Other.php model -
public function Employees()
{
return $this->hasMany('App\Other', 'other_id', 'id');
}
And in Employee.php model -
public function Others()
{
return $this->belongsTo('App\Employee', 'other_id', 'id');
}

NodeJS: Nested SQL query for custom REST API endpoint

I am creating a REST-API via NodeJS at the moment.
I created a MySQL database with these two tables:
table: physiotherapist = {(physio_id),(surname),(lastname),(appuser_id)}
--> PK = (physio_id)
--> FK = (appuser_id) and points on the PK of the second table
table: app_user = {(user_id),(username),(password)}
--> PK = (user_id)
For the REST-API endpoint I need the data of both tables.
For example, when I want the information of user with the id=3 and the api-enpoint is like 'localhost:3306/appusers/3' I want the data of both tables as a result.
This is what I got at the moment:
getUserById:function(id, callback) {
return db.query("Select * from user_physiO_app where user_id=?", [id], callback);
it'S only the data from the first table, so how do I get the data of the second table?
Thanks in regard!
Solved after the friendly advice of #Evert: I used the INNER JOIN syntax.
getUserById:function(id, callback) {
return db.query("Select * from user_physiO_app inner join physiotherapeut on
user_physiO_app.user_id = physiotherapeut.physiO_user_id where user_id=?", [id], callback);
}

How do I loop a MYSQL query multiple times and return the data from each looped query in node.js?

I have a database with a table called Inventory that has five columns: primary key, sku, item name, description, and price. I also have an array of SKUs called skus. My goal is to run a for-loop and query the Inventory table multiple times with each SKU to gather all of the information from each column about each SKU, and then output it.
I am fairly new to Node's asynchronous nature, and I'm having trouble with first obtaining all of the data from my table and THEN outputting it once it is all gathered and organized.
Here is my code:
var skus = [2, 1, 3, 4];
function inventoryLoop() {
for(var i=0; i<skus.length; i++)
{
var deferred = Q.defer();
connection.query("select * from Inventory where SKU = '"+skus[i]+"'", function(err, rows, fields) {
deferred.resolve(rows);
}); //connection.query
} //for-loop
return deferred.promise;
} //inventoryLoop()
Q.all(inventoryLoop()).then(function(results) {
console.log("results");
console.log(JSON.stringify(results));
}); //Q.all
This is my output:
[
{"inventoryObjectID":2,"SKU":"2","itemName":"Lego 2","description":"Lego 2 Description","price":2}
]
This is the output I'm seeking:
Results
[
{"inventoryObjectID":2,"SKU":"2","itemName":"Lego 2","description":"Lego 2 Description","price":2}
{"inventoryObjectID":1,"SKU":"1","itemName":"Lego 1","description":"Lego 1 Description","price":1}
{"inventoryObjectID":3,"SKU":"3","itemName":"Lego 3","description":"Lego 3 Description","price":3}
{"inventoryObjectID":4,"SKU":"4","itemName":"Lego 4","description":"Lego 4 Description","price":4}
]
If you iterate over the list to fetch the information for each item individually you end up performing multiple queries to the database. Instead you can create a more complex query that will get you all the information you need and therefore reduce the number of queries you perform.
In your case, because you have a list of sku you can ran a query where it fetches all the rows that match that sku. You can do that with the following query:
SELECT * FROM Inventory WHERE SKU='1' OR SKU='2' OR SKU='3' OR SKU='4'
You can create yet a better query that results in the same output as follows:
SELECT * FROM Inventory WHERE SKU IN ('1','2','3','4')
You can therefore write your query as follows and avoid looping through the list:
connection.query("SELECT * FROM Inventory WHERE SKU IN ("+skus+")",
function(err, rows, fields) {...});

How to get the last updated row using a single query

I searched enough before posting it.
My table structure:
aid | bid | cid | did |
Where aid, bid together are the primary keys.
When I update the value of cid using a where clause for aid, bid I also want to get the did value of the updated row.
Something like this:
$this->db->set('cid', 1, FALSE)
->where(array(
'aid' => $a_id,
'bid' => $b_id
))
->update('my_table')
->select('did');
The above query says:
Fatal error: Call to a member function select() on a non-object in...
I tried this:
How to get ID of the last updated row in MySQL?
Which is like 3 queries.
I'd suggest fetching the values you're about to update, store their IDs in an array, and run an UPDATE with a WHERE id IN (1, 2, ...).
What you're trying to do is not supported by MySQL. You'll need to run at least 2 queries, and since you're fetching the values the first time and already know what values you're updating, then you can also recreate the new row and it's values without using a query after UPDATE.
In your given example:
$this->db->set('cid', 1, FALSE)
->where(array(
'aid' => $a_id,
'bid' => $b_id
))
->update('my_table')
->select('did');
set(), where() and also select() returns an object that builds on the query. However update() return a value which is the results and doesn't have a function called select() and not set() and where() for that matter.