Update field in table with count of rows in another - mysql

I am building some custom email performance reporting in Marketing Cloud. I have one table which has a list of the emails sent in the last 30 days. It has a unique identifier, JobID. It has a few more columns where I want to insert for example how many times email was opened.
JobID EmailName Opens
37735 Test Email
I also have a table containing a list of all the opens of the emails sent in the last 30 days (using an inner join on the first table). I want to count the number of rows with job no. 37735 for example, and use this value to populate 'opens' in the above table.
JobID Subscriber DateOpened
37735 test#test.com 14/09/2017
37735 test2#test.com 14/09/2017
So from the above, I want a '2' in the 'Opens' column of the first table. Can anyone help?

If I understand correctly, you want an update. If so:
update table1 t1
set opens = (select count(*)
from table2 t2
where t2.jobid = t1.jobid
)
where t1.jobid = 37735;

Related

Comparing each colum in a row to every row in the database sql

I am building a bot that matches users based on a score they get, this score is taken from calculations done to data in a database on the request of the user.
I have only 1 table in that database and a few columns (user,age,genre,language,format,...etc).
What I want to do is, once the user clicks "find match" button on the chatbot, this user's data, which is already in the database will be compared to the other user's data in the same table and compare each column 1 by 1 of each row.
For example, the user's genre preference will be compared to each genre pref of the other users in each row of the table, when there is a match, 1 point is added, then language will be compared of each user and 1 point is given when there's a match. This will go to each column in each row and be compared with the user's. In the end, the users that has highest matching points will be recommended to this user.
What's the best way and approach to do that?
I am using nodejs and mysql database.
Thank you.
I see this as a self join and conditional expressions:
select t.*,
(t1.genre = t.genre) + (t1.language = t.language) + (t1.format = t.format) as score
from mytable t
inner join mytable t1 on t1.user <> t.user
where t1.user = ?
order by score desc
The question mark represents the id of the currently logged on user, for who you want to search matching users. The query brings all other users, and counts how many values they have in common over the table columns: each matching value increases the score by 1. Results are sorted by descending score.

JOINing tables while ignoring duplicates

So, let's say I have a hash/relational table that connects users, teams a user can join, and challenges in which teams participate (teams_users_challenges), as well as a table that stores entered data for all users in a given challenge (entry_data). I want to get the average scores for each user in the challenge (the average value per day in a given week). However, there is a chance that a user will somehow join more than one team erroneously (which shouldn't happen, but does on occasion). Here is the SQL query below that gets a particular user's score:
SELECT tuc.user_id, SUM(ed.data_value) / 7 as value
FROM teams_users_challenges tuc
LEFT JOIN entry_data ed ON (
tuc.user_id = ed.user_id AND
ed.entry_date BETWEEN '2013-09-16' AND '2013-09-22'
)
WHERE tuc.challenge_id = ___
AND tuc.user_id = ___
If a user has mistakenly joined more than one team, (s)he would have more than one entry in teams_users_challenges, which would essentially duplicate the data retrieved. So if a user is on 3 different teams for the same challenge, (s)he would have 3 entries in teams_users_challenges, which would multiply their average value by 3, thanks to the LEFT JOIN that automatically takes in all records, and not just one.
I've tried using GROUP BY, but that doesn't seem to restrict the data to only one instances within teams_users_challenges. Does anybody have any ideas as to how I could restrict the query to only take in one record within teams_users_challenges?
ADDENDUM: The columns within teams_users_challenges are team_id, user_id, and challenge_id.
If this is a new empty table, you can express your 'business rule' that a user should only join one team per challenge as a unique constraint in SQL:
alter table teams_users_challenges
add constraint oneUserPerTeamPerChallenge
unique (
user_id
, team_id
, challenge_id
);
If you can't change the table, you'll need to group by user and team and pick a single challenge from each group in the query result. Maybe pick just the latest challenge.
I can't test it, but if you can't clean up the data as Yawar suggested, try:
SELECT tuc.user_id, SUM(ed.data_value) / 7 as value
FROM entry_data ed
LEFT JOIN
(
select tuc.user_id, tuc.challenge_id from teams_users_challenges tuc group by tuc.user_id, tuc.challenge_id
) AS SINGLE_TEAM
ON SINGLE_TEAM.user_id = ed.user_id AND
ed.entry_date BETWEEN '2013-09-16' AND '2013-09-22'
WHERE tuc.challenge_id = ___
AND tuc.user_id = ___

Linq to SQL distinct join and group

I've been struggling with this Linq query...
I have the following 2 tables:
1) EmailRunHeaders - with columns: Id, EmailRunId, EmailId
2) EmailTrackers - with columns: Id, EmailId
Every day a batch of emails are sent. A unique "EmailRunId" is assigned to a batch/group of emails and each email is assigned an "EmailId". This info is then stored in the "EMailHeaders" table.
So, each emailId in the table will be unique, but the EmailRunId will appear more than once..since there is more than one email in each "batch" or run.
When an email is opened, using a HTTP handler, the open is logged in the EmailTracker table...where the particular EmailId is then stored. Since an email could be opened more than once, it is possible that a EmailId could appear more than once in this table.
I need the total number of emails opened, without double counting emails opened more than once, for every email run.
This is what I have so far. The nested query works fine..returning the total number of emails opened for each run, but only if there where at least 1 opened for each run.
I then tried wrapping that in another join to return all the distinct EmailRunIds from the header table..but that is where I am stuck..I don't know how to get the EmailRunId from "ah1".
from arh1 in EmailRunHeaders.Select(x => x.EmailRunID).Distinct()
join eo in
(from et in EmailTrackers
join arh2 in EmailRunHeaders
on et.EmailId equals arh2.EmailID.ToString() into j1
from j2 in j1.DefaultIfEmpty()
group j2 by j2.EmailRunID
into g
select new {runId = g.Key, count = g.Count()})
on arh1 equals eo.runId into tg
from tg2 in tg.DefaultIfEmpty()
select tg2

how to identify columns from 2 identical tables that doesn't have the same value

I have a system that moderates applicants, so first the admin needs to validate all of the applicants information before they can be list as accepted applicants, but the problem is every time the user modify any of his/her information, the user must reapply his/her application, so the admin will need to re-validate the applicants info,but i want to highlight those modified fields so the admin doesnt need to review all the information.
After spending some time on google, i came up to this idea,I created a trigger that insert the the record from table 1 before the modifications,to table 2. So now i want to select only the columns, that has been updated by the user but i don't know and i can't find something that does the said function.
Hopefully you have a primary key. In this example, I used 'email' and only check for changes in two columns:
SELECT *
from table1 t1
JOIN table2 t2 on t1.email = t2.email
WHERE (t1.fname != t2.fname)
OR (t1.lname != t2.lname)

Create Contacts Database Which Refers to Users Without Duplicates

My question is similar (but at the same time completely different) than this question:
Contacts Database
The question is simple: How can I create a Contacts database table which stores a user id and contact id without duplicating keys.
For example, if I have a table called Contacts, it would have a column user_id, and a column contact_id.
Once I do that, it should be as simple as inserting the user and the added contact. Once that is done though, how do I select all of a user's contacts? Also, how do I narrow down the contact entry enough to delete it if need be?
I ended up just creating a table with two foreign keys and then selecting them based on either of the fields.
For example (pseudo code--no specific language, just english):
Table Contact:
user = ForeignKey(from user table)
contact = ForeignKey(from user table)
Then whenever I need something from them, I'll check if the user field contains what I want and then I'll check if the contact field has what I want. This way I don't have to repeat records and I can still find what I need.
Thanks for your answers.
Similar to the question in the link. You would have 3 tables.
Table 1
User_ID
Name
PK(User_ID)
Table 2
Contact_id
Address
Phone_Number
etc...
PK(Contact_id)
Table 3
User_ID
Contact_id
PK(User_ID, Contact_id)
Here you would have ContactID in table 2 as an autoinc column.
Also, when inserting in Table 3, MySQL would throw an error if there is a duplicate.
To select all of a users contacts, use:
SELECT *
FROM Table_2 join Table_3
ON Table_2.Contact_id = Table_3.contact_id
WHERE Table2.User_id = <userid>
Or if you need it for a particular name, then
SELECT *
FROM Table_1 JOIN Table_2
ON Table_1.User_id = Table_2.User_id
JOIN Table_3
ON Table_2.Contact_id = Table_3.contact_id
WHERE Table1.name = <user name>
there are two questions.
" how do I select all of a user's contacts?"
So you have a table tbl_contacts(user_id, contact_id) both them are your primary key, so you won't get duplicated data.
I you want to list all contacts for user_id = ?
SELECT *
FROM tbl_contacts
WHERE user_id = ?
You might want to clarify your second question "Also, how do I narrow down the contact entry enough to delete it if need be?"
You probably have some other properties belong to the user's contact and you will need to use those properties to search for.(eg.: contact_name or contact_number) and when you have 1 record as a result of a query you can -> DELETE FROM tbl_contact WHERE contact_id = ?
If this is not the answer you wanted please clarify your question.