join table on itself as added columns mysql - mysql

I have a table that is used to hold answers to questions. Each question can be answered at different time intervals. Here's the table structure I have:
entry_index | ques_idx | ques | ans_idx | ans | entry_time | usr_id
1 1 ques1.. 1 ans 1 14:00 usr1
2 2 ques2.. 4 ans 4 14:00 usr1
3 1 ques1.. 2 ans 2 13:00 usr1
4 2 ques2.. 3 ans 3 13:00 usr1
What I am attempting to do is display the questions with the answers and the entry times as a column. For example:
ques | 14:00 | 13:00
ques1.. ans 1 ans 2
ques2.. ans 4 ans 3
Would a join be appropriate for this? I am at a complete loss. Any help would be greatly appreciated.

Related

how to generate student attendance percentage per course, when they have specific day in a week

hi guys i really newbie in sql, i need help to generate percentage of attendance, here is the table:
Table Schedule
Schedule_ID Course_ID Lecture_ID Start_Date End_Date Course_Days
1 1 11 2019-09-09 2019-12-08 2,4,6
2 3 4 2019-09-09 2019-12-08 3,4
3 4 13 2019-09-09 2019-12-08 2,5
4 5 28 2019-09-09 2019-12-08 3
5 2 56 2020-01-27 2020-04-26 2,4
6 7 1 2020-01-27 2020-04-26 4,5
7 1 11 2020-01-27 2020-04-26 2,4,6
8 7 22 2020-01-27 2020-04-26 2,3
9 8 56 2020-01-27 2020-04-26 5
10 3 37 2020-01-27 2020-04-26 5,6
Reference of days of week used in this data.
1: Sunday, 2:Monday, 3:Tuesday, 4:Wednesday, 5:Thursday, 6:Friday, 7:Saturday
Table course_attendance
ID STUDENT_ID SCHEDULE_ID ATTEND_DT
1 1 2 2019-09-10
2 1 2 2019-09-11
3 1 2 2019-09-17
4 1 2 2019-09-18
......
46 2 1 2019-12-02
47 2 1 2019-09-11
48 2 1 2019-09-18
49 2 1 2019-09-25
50 2 1 2019-10-09
51 2 1 2019-10-16
....
111 6 1 2019-09-23
112 6 1 2019-09-30
113 6 1 2019-10-07
114 6 1 2019-10-14
table student
ID NAME
1 Jonny
2 Cecilia
3 Frank
4 Jones
5 Don
6 Harry
i need to show up like this :
STUDENT_ID NAME Course_ID Attendance rate
1 Jonny 1 82%
2 Cecilia 1 30%
3 Frank 3 100%
4 Jones 2 100%
5 Don 2 25%
6 Harry 4 40%
EDIT this my last step to get percentage:
result:
with main as (
select ca.STUDENT_ID,
ca.SCHEDULE_ID,
s.COURSE_ID,
co.NAME as course_name,
st.NAME,
count(ca.ID) as total_attendance,
((CHAR_LENGTH(s.COURSE_DAYS) - CHAR_LENGTH(REPLACE(s.COURSE_DAYS , ',', '')) + 1) * 13) as attendance_needed
from univ.course_attendance ca
left join univ.schedule s on ca.SCHEDULE_ID = s.ID
left join univ.student st on ca.SCHEDULE_ID = st.ID
left join univ.course co on ca.SCHEDULE_ID = co.ID
group by ca.STUDENT_ID, ca.SCHEDULE_ID
)
select *,total_attendance/attendance_needed as attendance_percentage
from main
order by 1,2;
This can be done following three steps.
Step 1: Calculate the total number of days a particular course of a schedule has. It's a good thing the start_date is always on Monday and the end_date is always on Sunday, which makes the week complete and saves some trouble. By calculating the total number of weeks a course go through and the number of days a week has for that course, we can get the total number of days a particular course of a schedule has.
Step 2:Calculate the total number of days a student for a schedule. This is done fairly easily. Note: As the majority part of the table has been skipped and the OP has yet to provide the complete data set, I could only have 14 existing rows provided.
Step 3: Calculate the percentage for the attendance using the result from the above two steps and get other required columns.
Here is the complete statement I wrote and tested in workbench:
select t2.student_id as student_id,`name`,course_id, (t2.total_attendance/t1.total_course_days)*100 as attendance_rate
from (select schedule_id,course_id,
length(replace(course_days,',',''))*(week(end_date)-week(start_date)) as total_course_days
from Schedule) t1
JOIN
(select count(attend_dt) as total_attendance,student_id,schedule_id
from course_attendance group by student_id, schedule_id) t2
ON t1.schedule_id=t2.schedule_id
JOIN
student s
ON t2.student_id=s.id;
Here is the result set ( the attendance_rate is not nice due to the abridged course_attendance table):
student_id, name, course_id, attendance_rate
2, Cecilia, 1, 15.3846
6, Harry, 1, 10.2564
1, Jonny, 3, 15.3846

How to regress one's Y on a partner's variable X?

I investigate certain effects within a household / between partners. I have paneldata (person-year) for several variables, and a partner id. I would like to regress the outcome of a person on the dependent variable values of its partner. I don't know how to do this specification in Stata.
* Example generated by -dataex-. To install: ssc install dataex
clear
input float(year id pid y x)
1 1 3 9 2
2 1 3 10 4
3 1 . 11 6
1 2 4 20 2
2 2 4 21 6
3 2 3 22 7
1 3 1 25 5
2 3 1 30 10
3 3 2 35 15
1 4 2 20 4
2 4 2 30 6
3 4 . 40 8
end
* pooled regression
reg y x
* fixed effects regression
xtset year id
xtreg y x, fe
I can do pooled and fixed effects regressions. But even for the pooled / simple regression, how can I regress someones outcome on somebody else's independent variable?
Actually for Person 1, I need to regress 9/10/11 on 5/10/. and so on.
Person 2: regress 20/21/22 on 4/6/15
Person 3: regress 25/30/35 on 2/4/7
Person 4: regress 20/30/40 on 2/6/.
Idea: If there is no option in the regress function, I guess I could create new variables for each independent variable I have and name it x_partner. In this example x_partner should contain 5,10,.,4,6,15,2,4,7,2,6,. but I still don't know how to achieve this.
bysort id (year): egen x_partner = x[pid] // rough idea
The rough idea won't work. egen needs one of its own functions specified, and that alone makes the syntax illegal.
But the essence here is to look up the partner's values and put in new variables aligned with each identifier.
Thanks for using dataex.
rangestat from SSC, a community-contributed command, allows a one-line solution. Consider
* Example generated by -dataex-. To install: ssc install dataex
clear
input float(year id pid y x)
1 1 3 9 2
2 1 3 10 4
3 1 . 11 6
1 2 4 20 2
2 2 4 21 6
3 2 3 22 7
1 3 1 25 5
2 3 1 30 10
3 3 2 35 15
1 4 2 20 4
2 4 2 30 6
3 4 . 40 8
end
ssc install rangestat
rangestat wanted_y=y wanted_x=x if !missing(id, pid), interval(id pid pid) by(year)
list, sepby(id)
+-------------------------------------------------+
| year id pid y x wanted_y wanted_x |
|-------------------------------------------------|
1. | 1 1 3 9 2 25 5 |
2. | 2 1 3 10 4 30 10 |
3. | 3 1 . 11 6 . . |
|-------------------------------------------------|
4. | 1 2 4 20 2 20 4 |
5. | 2 2 4 21 6 30 6 |
6. | 3 2 3 22 7 35 15 |
|-------------------------------------------------|
7. | 1 3 1 25 5 9 2 |
8. | 2 3 1 30 10 10 4 |
9. | 3 3 2 35 15 22 7 |
|-------------------------------------------------|
10. | 1 4 2 20 4 20 2 |
11. | 2 4 2 30 6 21 6 |
12. | 3 4 . 40 8 . . |
+-------------------------------------------------+

Show entries for every item even if record doesn't exist in MySQL

I have two tables. The first table is a list of lots - table name lot. There are a total of 3 lots that are managed by three people and the fields are: lot.lotID, lot.LotName
Every day, these lots will collect eggs, but sometimes, the people collecting will forget to make the entry at the end of the day. These entries go into a table called deposit. This table has deposit.DepID, deposit.DepDate, deposit.LotID and deposit.DepAmount
I need to list every lot each day and get each deposit amount. If there is none made, instead of not displaying a record, it should show that the record is a NULL value or 0. For instance if no entry is inserted into the database for lot 2 on 2018-10-11, I should see this if I query two days' worth of data:
LotID | LotName | Date | DepAmount
1 | Sarah | 2018-10-09 | 67
2 | Dave | 2018-10-09 | 84
3 | Mike | 2018-10-09 | 78
1 | Sarah | 2018-10-10 | 100
2 | Dave | 2018-10-10 | 0
3 | Mike | 2018-10-10 | 49
Alternately, it is okay if lot 2 on 10-10 says:
2 | Dave | 2018-10-10 | {null}
Can someone give me a bit of direction here? It seems like it would be insanely simple, but I can't find much on the subject. Thanks in advance!!
PS - Here are the two tables:
lot:
LotID Name
1 Jim
2 Mary
3 Jeff
4 Steve
5 Clinton
6 George
7 Jennifer
and deposit:
DepDate DepAmount UserID LotID
2018-10-09 07:09:13 150.00 1
2018-10-09 07:21:22 345.00 2
2018-10-09 19:18:33 283.00 3
2018-10-09 19:37:51 100.00 4
2018-10-09 14:11:47 357.00 8 5
2018-10-09 14:21:43 5324.00 8 6
2018-10-09 14:27:46 564.50 8 7
2018-10-10 14:32:29 3543.75 6 2
2018-10-10 23:12:40 234.00 10 3
2018-10-10 07:09:13 52.00 1
2018-10-11 07:09:13 234.00 3
2018-10-10 07:09:13 764.00 4
2018-10-10 07:09:13 123.00 6
2018-10-10 07:09:13 764.00 7
This is a tricky problem as a straight LEFT JOIN will not work due to a person having values for dates other than the one which has no value in deposit. So we need to first CROSS JOIN lot with a list of all the dates in deposit to get a set of all people and all dates i.e.
SELECT l.LotId, l.LotName, dt.Date
FROM lot l
CROSS JOIN (SELECT DISTINCT DepDate AS Date
FROM deposit) dt
Output:
LotId LotName Date
1 Sarah 2018-10-09
2 Dave 2018-10-09
3 Mike 2018-10-09
1 Sarah 2018-10-10
2 Dave 2018-10-10
3 Mike 2018-10-10
Then we can LEFT JOIN this result with the deposit table to get our list of deposits for each day, using COALESCE to convert NULL values to 0:
SELECT l.LotId, l.LotName, dt.Date, COALESCE(d.DepAmount, 0) AS DepAmount
FROM lot l
CROSS JOIN (SELECT DISTINCT DepDate AS Date
FROM deposit) dt
LEFT JOIN deposit d ON d.LotId = l.lotId AND d.DepDate = dt.Date
ORDER BY Date, l.LotId
Output:
LotId LotName Date DepAmount
1 Sarah 2018-10-09 67
2 Dave 2018-10-09 84
3 Mike 2018-10-09 78
1 Sarah 2018-10-10 100
2 Dave 2018-10-10 0
3 Mike 2018-10-10 49

ROW COUNT in MYSQL

In mysql, I got table "a" as follow
ID USERNAME SUBJECT_ID
1 ALAN 1
2 ALAN 2
3 ALAN 3
4 ALAN 4
5 ALAN 5
6 JOHN 6
7 ALAN 7
8 JOHN 8
9 ALAN 9
I just want to know username = ALAN takes how many subject and how generate a new column to C become
ID USERNAME SUBJECT_ID C
1 ALAN 1 1
2 ALAN 2 2
3 ALAN 3 3
4 ALAN 4 4
5 ALAN 5 5
7 ALAN 7 6
9 ALAN 9 7
The column is group by USERNAME and generate the row count.How should I query and generate C field?
The query I have tried, but I don't know how to generate "C"
SELECT ID,USERNAME,SUBJECT_ID,C FROM a WHERE USERNAME = "ALAN" GROUP BY SUBJECT_ID
Please help, thanks.
You can use Row number in mysql, this way:
SELECT T1.*,#rownum := #rownum+1 as C
FROM TableName T1,(SELECT #rownum := 0) r
WHERE T1.Username LIKE '%ALAN%'
Result:
ID USERNAME SUBJECT_ID C
-----------------------------
1 ALAN 1 1
2 ALAN 2 2
3 ALAN 3 3
4 ALAN 4 4
5 ALAN 5 5
7 ALAN 7 6
9 ALAN 9 7
Example in SQL Fiddle.

SQL query to show zero instead of not shown record

I have these two tables:
Reception
id reception_date tin_lot company_id client_id quantity weight
1 2013-12-03 00:00:00 1 1 1 10 1980.00
2 2013-12-03 00:00:00 2 1 1 1 150.00
3 2013-12-13 00:00:00 3 1 2 10 4500.00
4 2013-12-13 00:00:00 4 2 5 5 2300.00
Payment
id payment_date amount reception_id
1 2013-12-03 00:00:00 500.0 1
2 2013-12-03 00:00:00 1200.0 3
The result I want to obtain is the following:
Expected result
id reception_date tin_lot client_id weight payment_made
1 2013-12-03 00:00:00 1 1 1980.00 500.0
2 2013-12-03 00:00:00 2 1 150.00 0.0
3 2013-12-13 00:00:00 3 2 4500.00 1200.0
4 2013-12-13 00:00:00 4 5 2300.00 0.0
I'm trying this query:
select rec.id
rec.reception_date,
rec.tin_lot,
rec.client_id,
rec.weight,
pay.payment_made
from liquidation.reception rec, liquidation.payment pay
where pay.recepcion_id=rec.id
But it doesn't list the receptions with no payment.
Please help me. Thanks in advance.
you need to Left Join the payment table:
from liquidation.reception rec
left join liquidation.payment pay on ( pay.recepcion_id=rec.id)
That is because you need to learn to use left outer join and proper join syntax. Just don't use a comma in a from clause any more.
Here is the query you want:
select rec.id, rec.reception_date, rec.tin_lot, rec.client_id, rec.weight,
coalesce(pay.payment_made, 0) as payment_made
from liquidation.reception rec left outer join
liquidation.payment pay
on pay.recepcion_id = rec.id;