Join and Union with Entity Framework - mysql

I have two tables (clients and emails), one with customer's data, including a main email address, and another one with additional email addresses.
I need to validate the user from one of their many email addresses, no matter if it is on clients or emails table. I've come up with this SQL sentence which works fine:
set #email = 'client#domain.com';
select c1.credits > 0 as Allowed, c1.Email as MainEmail from
customers c1 inner join (select ClientId, Email FROM customers WHERE
Email=#email union all select ClientId, Email FROM emails WHERE Email=#email) e1
on c1.ClientId = e1.ClientId;
How to write this query in LINQ to Entities with method-based syntax?

If i understand correctly,
Customer may or may not have the email (Additional) in emails table.
Also, Customer have more than one additional emails entry in emails table. Like below
List<Customer> customers = new List<Customer>
{
new Customer { ClientId = 1, Email = "client1#domain.com", Credits = 2 },
new Customer { ClientId = 2, Email = "client2#domain.com", Credits = 1 },
new Customer { ClientId = 3, Email = "client3#domain.com", Credits = 1 },
};
List<Emails> emails = new List<Emails>
{
new Emails { ClientId = 1, Email = "client1-2#domain.com" },
new Emails { ClientId = 1, Email = "client1-3#domain.com" },
new Emails { ClientId = 2, Email = "client2-1#domain.com" },
};
In that case, Use the below query to get it done,
var result = from c in customers
let _emails = emails.Where(e => c.ClientId == e.ClientId).Select(t => t.Email)
where c.Email == "client3#domain.com" || _emails.Contains("client3#domain.com")
select new
{
Allowed = c.Credits > 0,
MainEmail = c.Email
};
I hope it helps you.

Related

MOODLE. Problem with definition user role for course

I'm trying make solution by Using MOODLE create users and enroll them in courses via SQL
Add user - done
Add user to course - done
But user without role into course. No roles in role column.
'googleoauth2' as auth value for login with social network API. It's work.
The problem is remains If I change 'auth' value to 'manual'.
Into database all records as in queries.
Help, please.
UPD: sorry, I need to change enlorID to courseID in instanceid field...
Code:
async function test(){
var query = `INSERT INTO mdl_user (auth, confirmed, username, password, firstname, lastname, email, mnethostid)
VALUES ('googleoauth2', 1, '${pseudo}', 'not cached', '${name}',
'${secondname}', '${email}', 1);`;
var insertOutput = await getMysqlQuery(query);
var userId = insertOutput.results.insertId;
var courseRecords = await getMysqlQuery("SELECT id FROM mdl_course WHERE idnumber=\"" + shortname + "\"");
if(courseRecords.length < 1)
throw 'Course not found';
var courseId = courseRecords.results[0].id;
var enrolRecords = await getMysqlQuery(`SELECT id FROM mdl_enrol WHERE courseid=${courseId} AND enrol='manual';`);
if(enrolRecords.length < 1)
throw 'Enrol not found';
var enrolId = enrolRecords.results[0].id;
var contextRecords = await getMysqlQuery(`SELECT id FROM mdl_context WHERE contextlevel=50 AND instanceid=${courseId};`);
if(contextRecords.length < 1)
throw 'Context not found';
var now = (new Date()).getTime() / 1000 ;
var contextId = contextRecords.results[0].id;
await getMysqlQuery(`INSERT INTO mdl_user_enrolments (status, enrolid, userid,
timestart, timeend, timecreated, timemodified) VALUES
(0, ${enrolId}, ${userId}, '${now}', '${now + 60*60*24*2}', '${now}', '${now}')`);
await getMysqlQuery(`INSERT INTO mdl_role_assignments
(roleid, contextid, userid, timemodified)
VALUES (5, ${contextId}, '${userId}', '${now}');`);
}
It looks like you are using JavaScript. I have a solution to enroll the student in course with a role in PHP programming language as below.
$plugin = enrol_get_plugin('manual');
$course = $DB->get_record('course', array('id' => $courseid)); // Get course object by courseid
$instance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'));
if (empty($instance)) {
// Only add an enrol instance to the course if non-existent.
$enrolid = $plugin->add_instance($course);
$instance = $DB->get_record('enrol', array('id' => $enrolid));
}
// Take care of timestart/timeend in course settings.
$timestart = time();
// Remove time part from the timestamp and keep only the date part.
$timestart = make_timestamp(date('Y', $timestart), date('m', $timestart), date('d', $timestart), 0, 0, 0);
if ($instance->enrolperiod) {
$timeend = $timestart + $instance->enrolperiod;
} else {
$timeend = 0;
}
// Enrol the user with this plugin instance.
$plugin->enrol_user($instance, $user->id, $roleid); // This will enroll user in course with roleid you provided.

Replacing object id with coresponding name from other object

Im very new to angular so ill try to describe the problem as cleary as i can.
Im tring to make and single page app with some information about trading between people. AS for backend im using MySQL database + nodejs as a backed server and angular as frontend.
The problem is i have a person table with ID and a Name, Balance for each person.
Then i have a table where i store all the transactions between the people ( Id, Giver ID , Taker ID , Amount ).
At the frontend when i get the information about the transactions i get IDS of the giver and taker, but i want to replace them with the coresponding name from persons table / object.
I have clearly no idea how to manag this. I thought about looping trought the transactions objects and replace each ID in the array with a name.
Something like in this post
The Transaction object:
[Object]0: id: 1 giver_id: 1 taker_id: 5 amount: 50
Persons object:
[Object]0: balance:"-50" id:1 name:"Edgars"[Object]1: balance:"0" id:2 name:"Jānis"
So i want to replace the giver_id 1 with the name Edgars because as FK for giver id maches the persons id.
I dont want a clear answear but atleast a way to dig in.
My suggestion would be to handle the join between the two tables on the server side.
The UI will make one webservice call to get the transactions. The response should be an array of transactions and each transaction object should have the name of the giver and the taker.
You will need a SQL query to join the two tables. A simple join SQL would look like this.
select t.id as TRANS_ID, gp.name as GIVER, tp.name as TAKER, t.amount
from transaction t
join person gp on t.giver_id = gp.id
join person tp on t.taker_id = tp.id;
The JSON response to the UI would look like this:
[
{
"trans_id": 1,
"giver_name": "James",
"taker_name": "Michael",
"amount": 50
},
{
"trans_id": 2,
"giver_name": "Jim",
"taker_name": "Mike",
"amount": 100
}
]
This way, all of your logic would be on the server side and your UI only has to display the data.
You could map a new list from both lists:
var newList = transactionsList.map(function(t) {
var giver,taker;
giver = personList.find(function(p) {
return p.id == t.giver_id;
});
taker = personList.find(function(p) {
return p.id == t.taker_id;
});
if(giver && taker) {
t.giver_name = giver.name;
t.taker_name = taker.name;
return t;
}
else {
return undefined;
}
});
Or if you only need to this on one object:
function transformTransaction(t) {
var giver,taker;
var newTransaction = angular.copy(t);
giver = personList.find(function(p) {
return p.id == t.giver_id;
});
taker = personList.find(function(p) {
return p.id == t.taker_id;
});
if( giver && taker ) {
newTransaction.giver_name = giver.name;
newTransaction.taker_name = taker.name;
return newTransaction;
}
else {
return undefined;
}
}

Writing a MYSQL Following Users Query

I'm building an app where a user can follow other users and be followed.
A user can also look at who another user is following.
Now lets say user1 is looking at who user2 is following, I need to find all the people IDs that user2 is following and compare it against who user1 is following.
Instead of returning only the IDs of all the users that match both user1 and user2 (which I've seen in other forums), I need to retrieve all user2's following IDs and User Names as well as a flag that indicates if the followed person is also followed by user1.
I've got it to work in PHP with a double for loop of each Query, but I worry that this code will be expensive and would be far better optimized with a single MYSQL query.
Relevant tables and columns:
following_table
follower_id
followed_id
following: varchar -- 'true' or 'false'
user_table
user_id
user_name
Here is my PHP code:
$user_id1 = '1991';
$myFollowingQuery = "SELECT following_table.followed_id, user_table.user_name
FROM following_table
INNER JOIN user_table ON
following_table.followed_id = user_table.user_id
WHERE following_table.following = 'true'
AND following_table.follower_id = '$user_id1'";
$user_id2 = '1985';
$userFollowingQuery = "SELECT following_table.followed_id, user_table.user_name
FROM following_table
INNER JOIN user_table ON
following_table.followed_id = user_table.user_id
WHERE following_table.following = 'true'
AND following_table.follower_id = '$user_id2'";
$userFollowingResult = mysql_query($userFollowingQuery)
or doResponse('error',"Couldn't connect to the database");
$myFollowingResult = mysql_query($myFollowingQuery)
or doResponse('error',"Couldn't connect to the database");
for($i = 0; $i< mysql_num_rows($userFollowingResult);$i++){
$loopArray = array(followed_id => mysql_result($userFollowingResult,$i,"followed_id"),
followed_name => mysql_result($userFollowingResult,$i,"user_name"));
for($j = 0; $j< mysql_num_rows($myFollowingResult);$j++){
if(mysql_result($userFollowingResult,$i,"followed_id")
==mysql_result($myFollowingResult,$j,"followed_id")) {
$loopArray['is_following'] = 'true';
break;
}
if($j==mysql_num_rows($myFollowingResult)-1){
$loopArray['is_following'] = 'false';
break;
}
}
$resultArray[$i] = $loopArray;
}
echo json_encode($resultArray);
Here is a simplified query:
http://sqlfiddle.com/#!2/6b8d6/3
SELECT
user.user_id,
user.user_name,
he.follower_id AS follower_id,
IF(me.followed_id,1,0) AS metoo
FROM following AS he
INNER JOIN user
ON user.user_id = he.followed_id
LEFT JOIN following AS me
ON me.follower_id = 1
AND me.followed_id = he.followed_id
WHERE he.follower_id = 2

LINQ to SQL - Group By/Where

I'm trying to implement a group messaging feature in ASP.NET MVC. I want to display a list of all threads for a specific ContactID, displaying the latest message in that thread (no matter who it's from). I've set up my table as below:
MessageID ThreadID MessageBody ContactID
10000004 300152,300160, msg1 300160
10000005 300152,300160, msg2 300160
10000008 300152,300160, msg3 300152
I was able to display the latest message grouped by ThreadID. Ex:
ThreadID Count LatestMessage
300152,300160, 3 10000008
However, if I add the Where clause before the group by (see below), it'll filter on ContactID first before doing the group by, and producing this result:
ThreadID Count LatestMessage
300152,300160, 2 10000005
Here's the code:
var result = from s in pdc.Messages
where s.ContactID == contactID
group new { s } by new { s.ThreadID } into d
let maxMsgID = d.Max(x => x.s.MessageID)
select new {
ThreadID = d.Key.ThreadID,
Count = d.Count(item => item.s.MessageType == GlobalConstants.MessageTypeText),
LastMessage = d.Where(x => x.s.MessageID == maxMsgID)
};
Is there a way to do the group by and then filter on ContactID?
var result = from s in pdc.Messages
where s.ContactID == contactID
group new { s } by new { s.ThreadID } into d
select new {
ThreadID = d.Key,
Count = d.Count(item => item.s.MessageType == GlobalConstants.MessageTypeText),
LastMessage = d.select(x => x.s.MessageID).Max(),
};
Hope it can help you and have a nice day.

LINQ join and group

How to expand this query:
public Dictionary<int, List<TasksInDeal>> FindAllCreatedTasks()
{
return (from taskInDeal in db.TasksInDeals
where taskInDeal.Date > DateTime.Now && taskInDeal.Date < DateTime.Now.AddDays(7)
group taskInDeal by taskInDeal.CreatedByUserID
into groupedDemoClasses
select groupedDemoClasses).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
}
into something like this:
public Dictionary<int, List<TaskForNotification>> FindAllCreatedTasks()
{
return (from taskInDeal in db.TasksInDeals
join user in db.Users on taskInDeal.CreatedByUserID equals user.UserID
where taskInDeal.Date > DateTime.Now && taskInDeal.Date < DateTime.Now.AddDays(7)
group taskInDeal by taskInDeal.CreatedByUserID
into groupedDemoClasses
select new TaskForNotification
{
Email = user.Email,
TaskInDealField1 = taskInDeal.TaskInDealField1,
TaskInDealField2 = taskInDeal.TaskInDealField2,
TaskInDealField3 = taskInDeal.TaskInDealField3,
...
}
).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());
}
So, to first query I need to join email from other table.
// do the date logic up front, not in the database.
DateTime now = DateTime.Now
DateTime weekFromNow = now.AddDays(7);
// pull the joined rows out of the database.
var rows =
(
from taskInDeal in db.TasksInDeals
where taskInDeal.Date > now && taskInDeal.Date < weekFromNow
join user in db.Users
on taskInDeal.CreatedByUserID equals user.UserID
select new {TaskInDeal = taskInDeal, UserEmail = user.Email}
).ToList();
// shape the rows in memory
Dictionary<int, List<TaskForNotification>> result =
(
from row in rows
let taskForNotification = new TaskForNotification
{
Email = row.UserEmail,
TaskInDealField1 = row.TaskInDeal.TaskInDealField1,
TaskInDealField2 = row.TaskInDeal.TaskInDealField2,
TaskInDealField3 = row.TaskInDeal.TaskInDealField3,
...
}
group taskForNotification by row.TaskInDeal.CreatedByUserID
// without an "into", group by ends the query.
).ToDictionary(g => g.Key, g => g.ToList());
When you group, bear this in mind. Groups in SQL have only keys and aggregates. Groups in LINQ have keys, aggregates and elements! If you ask the database for groups, and then ask for the elements - SQL couldn't provide you with those elements in a single query. You'll wind up automatically repeatedly re-querying using the group's key as a filter.