I have a Query that Groups by a column which is needed so I get the result that I need, and then I need to return results which should be done by Grouping the previous results by another field.
So basically I have a Survey table,
sql = SELECT * FROM Survey S
WHERE S.UserId = 79
Group By S.SurveyNumber
Having SUM (S.Counter) <> 0 ORDER BY S.SubmittedDate DESC
This returns the Survey grouped by the Number, and then I need to Group the result by SurveyName and return the Last Submitted Survey for that SurveyName ( Max(submittedDate).
Can I achieve this in using one query ? If I have
GroupBy S.SurveyNumber, S.SurveyName
Then it will try to find that have BOTH of the columns same.
How do I do this ?
i think it works:
SELECT
S2.SurveyName
,SUM(S2.Count) as SurveyCount
FROM (
select
SUM(S.SurveyNumber) as Count
,S.SurveyName
FROM Survey S
where S.SurveyNumber <> 0
Group By S.SurveyNumber,S.SurveyName
) as S2
Group By S2.SurveyName
This is how I understand this:
Every survey belongs to one user. You want the survey of one particular user.
The table is actually not a Survey table (with one record representing a survey), but a kind of survey chronology table. There are multiple records per survey.
You must look at all records per survey in order to know whether its paid.
For each paid survey you want the last chronology record.
You have already shown how to check whether a survey is paid. Now select the last date for them (the maximum date). Based on this get the related records from the table.
select *
from survey
where (surveynumber, submitteddate) in
(
select surveynumber, max(submitteddate)
from survey
where userid = 79
group by surveynumber
having sum(counter) <> 0
);
I may be wrong though, because you make it sound like a survey number is somehow independent from the survey name. (One survey number with various names? The same survey name for multiple survey numbers?)
You would certaily benefit from a better data model with at least two separate tables for survey and survey details.
Related
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.
I have a quiz_tracking table (in mysql) that contains the ff fields:
subjectid - the id of the subject ( think of your subjects in school)
assessmentname - the name of the assessment ( think of it as exam or like chapter exams, the exams you found at the end of each chapter) found in each subject
questionid - the id of the question
userid - the id of the user who took the exam
attempt - attempt number
answer - answer given
score - score gained for this question
rownum - disregard this column, i only put in this one so its easier to point out which row numbers i am particularly interested in.
When the user takes a quiz, the records are recorded here. The assessments have different number of questions. For this example, first assessment has 3, second assessment has 3, third assessment has 1. The user can leave the quiz at the middle, in this case the answer column will be null since the quiz taker abandoned it.
I created a sql fiddle for the table and the data.
http://sqlfiddle.com/#!9/a41473/1
Basically, what I want to come up is I need to filter this data set and present a data set that only contains completed assessment attempts. Meaning, if the assessment has 3 questions and all these questions were answered (answer is not null) then that should be in the filtered data set.
The way I figured out how to determine if there was a complete assessments is via this sql:
select max(a.question_count) from (
select count(distinct qt.questionid) as 'question_count'
from quiz_tracking qt
where qt.subjectid=22380
and qt.assessmentname = 'first assessment'
and qt.userid in (555,121)
group by qt.attempt, qt.userid ) a )
I count all the question ids. Then i do a
having ( sum(if(answer is not null,1,0)) = result of above subquery.
The assumptions here are,
the subjectid is provided,
all the assessment names are provided
all the userids are provided.
In the sql fiddle,i can do it for 1 assessment (e.g. 'first assessment'), but what I need to do is to produce a filtered data set that contains all the assessments (first assessment, second assessment, third assessment). The expected result should be row numbers 1,2,3,4,5,6,12,13,14,15,16,17,21,22.
Simply join the main table to an aggregate derived table that calculates question count and answer count, then in outer query return when both are equal:
select z.*, q_cnt.question_count, q_cnt.answer_count
from quiz_tracking z
inner join
(select c.userid, c.subjectid, c.assessmentname, c.attempt,
count(distinct c.questionid) as 'question_count',
sum(if(c.answer is not null,1,0)) as 'answer_count'
from quiz_tracking c
group by c.userid, c.subjectid, c.assessmentname, c.attempt) q_cnt
on q_cnt.userid = z.userid
and q_cnt.subjectid = z.subjectid
and q_cnt.assessmentname = z.assessmentname
and q_cnt.attempt = z.attempt
where q_cnt.question_count = q_cnt.answer_count
SQL Fiddle DEMO
I'm sorry if my question irrelevant. Because I'm not expert of mysql.
I have surveys in my website. If someone votes my survey, i want to show survey results to the voter.
Here is the DB Structure;
surveys Table (Includes Survey Name Description and survey_id)
survey_choices Table (Includes Survey Chocies and related with survey_id to Surveys Table)
I'm trying to calculate only visible survey choices %percentage.
If i have only 1 survey, it's calculating correct results. But if i have more than 1 survey, mysql calculating whole survey_vote_count values of all table.
Here is my MySQL query;
SELECT
survey_vote_id, survey_vote_name, survey_vote_count, survey_id,
survey_vote_count * 100 / t.s AS survey_percentage
FROM survey_votes
CROSS JOIN (SELECT SUM(survey_vote_count) AS s FROM survey_votes) t
WHERE visibility = :visibility
AND survey_id = :surveyId
ORDER BY `survey_votes`.`order_id` ASC
How can i calculate for eg only survey_id = 1 and visibility = 1 %percentage = %100?
Any help will greatly appricated.
You should add the same condition to your cross join. At the moment, in your select you sum all survey_vote_count without the same where condition (visibility and survey_id.
I am working on an employee management/reward system and need to be able to show a single "transaction history" page that shows in chronological order the different events that the employee has experienced in one list. (Sort of like how in facebook you can goto your history/action section and see a chronological list of all the stuff that you have done and affects you, even though they are unrelated to eachother and just have you as a common user)
I have different tables for the different events, each table has an employee_id key and an "occured" timestamp, some table examples:
bonuses
customers
raise
complaints
feedback
So whenever an event occurs (ie a new customer is assigned to the employee, or the employee gets a complaint or raise) a new row is added to the appropriate table with the employee ID it affects and a timestamp of when it occured.
I need a single query to pull all records (upto 50 for example) that include the employee and return a history view of that employee. The field names are different in each table (ie the bonus includes an amount with a note, the customer includes customer info etc).
I need the output to be a summary view using column names such as:
event_type = (new customer, bonus, feedback etc)
date
title (a brief worded title of the type of event, specified in sql based on the table its referencing)
description (verbiage about the action, such as if its event_type bonus display the bonus amount here, if its a complain show the first 50 characters of the complaint message or the ID of the user that filed the complaint from the complaints table. All done in SQL using if statements and building the value of this field output based on which table it comes from. Such as if its from the customers table IF current_table=customers description='A customer was assigned to you by'.customers.assigner_id).
Ideally,
Is there any way to do this?
Another option I have considered, is I could do 5-6 different queries pulling the records each from their own table, then use a mysql command to "mesh/interleave" the results from all the queries into one list by chronological order. That would be acceptable too
You could use a UNION query to merge all the information together and use the ORDER BY clause to order the actions chronologically. Each query must have the same number of fields. Your ORDER BY clause should be last.
The examples below assume you have a field called customer_name in the customers table and bonus_amount in the bonuses table.
It would look something like this:
SELECT 'New Customer' as event_type, date,
'New customer was assigned' as title,
CONCAT('New Customer: ', customer_name, ' was assigned') as description
FROM customers
WHERE employee_id = 1
UNION
SELECT 'Bonus' as event_type, date,
'Received a bonue' as title,
CONCAT('Received a bonus of $', FORMAT(bonus_amount, 2), '.') as description
FROM bonuses
WHERE employee_id = 1
UNION
...
ORDER BY date DESC;
My actual tables are much more complex but here is a simplified example of the problem I am trying to work out.
Table contact: ContactID, ContactName, Pending
Table purchase: PurchaseID, ContactID, Amount, Pending, Date
Table contact_purchase_link: ContactID, PurchaseID (although it may seem like the link table is not necessary in this simplified example it is necessary in the large table schema)
Here is the query that I currently have:
SELECT DISTINCT contact.ContactID,
( SELECT SUM(Amount)
FROM purchase
WHERE purchase.ContactID = contact.ContactID
AND purchase.Pending = 0
) totalpurchase
FROM contact
INNER JOIN ( contact_purchase_link JOIN purchase
ON (contact_purchase_link.PurchaseID = purchase.PurchaseID
))
USING (ContactID)
WHERE purchase.Date > '2013-12-06' AND
AND contact.Pending =0
The problem is that I want the totalpurchase (the sum of the amount field) to be limited to the search criteria of the purchase table - meaning the query should only return the sum of the purchases after the specified date per contact. I think in order to use a group by clause the query would have to be based off the purchase table but I need the query to use the contact table so that all contacts are listed with their total purchase amounts and other relevant client data.
Is there any way to do this within one query?
To further clarify:
This query is being generated as part of a search engine. An example of why a query like this would be done is if a user wanted to generate a contact list of lastnames starting with A with purchases of a specific item or as in this example of purchases for a specific date. So that in general the query would have to generate a list of all contacts and their data (with possible search criteria on the type of contact such as all lastnames starting with 'A' etc.) and the query can also include search criteria on the purchase table such as the date of the purchase and whether the purchase was for specific items etc.
I am trying to add in the option to also list the sum of the purchases for the contact however that sum has to be limited to the search criteria for the purchase table as well and not the sum of all the contacts purchases.
If I understand your question correctly, you need to move the date comparison inside the first subquery:
SELECT DISTINCT contact.ContactID,
( SELECT SUM(Amount)
FROM purchase
WHERE purchase.ContactID = contact.ContactID
AND purchase.Pending = 0
AND purchase.Date > '2013-12-06'
) totalpurchase
FROM contact
INNER JOIN ( contact_purchase_link JOIN purchase
ON (contact_purchase_link.PurchaseID = purchase.PurchaseID
)
USING (ContactID)
WHERE purchase.Date > '2013-12-06'
AND contact.Pending =0
But the comments are right - I corrected a couple of what appears to be syntax errors, and I'm not sure about the join to contact_purchase_link. Improve your question and my answer will be less like guesswork.