Each childrow has a parentid and position. For childrows with the same position there is one row where start='1'.
What i'm trying to do is return the pending rows with their start row.
The results that should be shown are; start(owen) pending(dave,paul). This is because they have the same position. Here is the SQL fiddle http://sqlfiddle.com/#!2/e6e54/1
id | name | parentid| position| start | pending |
1 | mike | 0 | 0 | 0 | 0 |
2 | dave | 1 | 1 | 0 | 1 |
3 | paul | 1 | 1 | 0 | 1 |
4 | john | 1 | 2 | 1 | 0 |
5 | bret | 1 | 2 | 0 | 0 |
6 | owen | 1 | 1 | 1 | 0 |
7 | rick | 1 | 3 | 1 | 0 |
8 | jaye | 1 | 3 | 0 | 0 |
$getquery = mysql_query("select child.*
from `mytable` child inner join `mytable` parent
on parent.id=child.parentid
inner join `mytable` child2 on child.parentid=child2.parentid
and child2.pending='1'
where child.start='1' ORDER BY child.id DESC");
while($row=mysql_fetch_assoc($getquery)) {
$name = $row['name'];
echo "<p>Name: $name </p>";
}
select * from `mytable` order by position, pending
You can add a where position=1 clause if that's the only position of interest.
Related
I have a DB where I have stored a table with user information, a table with test (answers and points) and a table with user's answers for each question. Each question is worth in total 1 point and could have one or more correct answers. If all of the answers are correct, and the user check just one, he will receive just 0.25 points.
I want to make a query to check total points for each user, but I don't find a good method.
User table:
+--------+------------+-----------+-------------------+------------+--------+
| userID | first_name | last_name | email | password | points |
+--------+------------+-----------+-------------------+------------+--------+
| 1 | Jhon | Jhonny | jhon#yahoo.com | secretPass | 0 |
| 2 | Dan | Dan | dan#yahoo.com | 1234 | 0 |
| 3 | Dick | Pop | dd#yahoo.com | 123456 | 0 |
| 4 | Mihaela | Micky | mihaela#yahoo.com | pass12 | 0 |
+--------+------------+-----------+-------------------+------------+--------+
Question table:
(1 means that answer is good - we can have multiple correct answers)
+------------+--------------------------------------------------+---+---+---+---+
| questionID | question | a | b | c | d |
+------------+--------------------------------------------------+---+---+---+---+
| 1 | which of these are colors? | 1 | 0 | 0 | 1 |
| 2 | which of these are fruits? | 1 | 1 | 1 | 0 |
| 3 | which of these are programming language? | 0 | 1 | 1 | 0 |
| 4 | What is IPv6? | 0 | 0 | 0 | 1 |
+------------+--------------------------------------------------+---+---+---+---+
User's answer table:(1 means the user choose that answer but may be inccorect )
+------------+--------+---+---+---+---+
| questionID | userID | a | b | c | d |
+------------+--------+---+---+---+---+
| 1 | 1 | 1 | 1 | 0 | 0 |
| 2 | 1 | 1 | 1 | 1 | 0 |
| 1 | 3 | 1 | 0 | 1 | 1 |
| 1 | 4 | 1 | 1 | 1 | 0 |
| 3 | 1 | 1 | 0 | 1 | 1 |
| 4 | 1 | 1 | 0 | 1 | 1 |
| 1 | 2 | 1 | 1 | 0 | 0 |
| 2 | 2 | 0 | 1 | 0 | 1 |
| 3 | 2 | 0 | 1 | 1 | 1 |
| 4 | 2 | 1 | 1 | 0 | 1 |
| 2 | 3 | 1 | 0 | 0 | 1 |
| 3 | 3 | 1 | 0 | 1 | 1 |
| 4 | 3 | 1 | 0 | 1 | 1 |
| 2 | 4 | 0 | 1 | 1 | 1 |
| 3 | 4 | 1 | 0 | 0 | 1 |
| 4 | 4 | 0 | 0 | 1 | 0 |
+------------+--------+---+---+---+---+
Try this
SELECT
a.*,
u.name,
q.*,
# (a.a & q.a) + (a.b & q.b) + (a.c & q.c) + (a.d & q.d) userCorrects,
# (a.a + a.b + a.c + a.d) questionCorrects,
((a.a & q.a) + (a.b & q.b) + (a.c & q.c) + (a.d & q.d)) / (a.a + a.b + a.c + a.d) as userGrade
FROM
answer a
INNER JOIN
user u ON a.userID = u.id
INNER JOIN
question q ON a.questionID = q.id
You'd join questions and answers and add up correct answers. The formula per answer is simply: number of correct answers divided by 5. You'd GROUP BY user ID and SUM to get results per user.
select u.userid, u.first_name, u.last_name, counted.points
from
(
select
a.userid,
sum(((a.a = q.a) + (a.b = q.b) + (a.c = q.c) + (a.d = q.d) + (a.e = q.e)) / 5)
as points
from question q
join answer a on a.questionid = q.questionid
group by a.userid
) counted
join users u on u.userid = counted.userid;
In MySQL true = 1 and false = 0, so (a.a = q.a) is 1 when correct and 0 when wrong.
Nice question...!!!
I think this query will help you with all possible cases that may occur in this scenario.
SELECT
u.userID, u.first_name, u.last_name, u.email,
SUM(1 - ((!(answer.a = question.a)) + (!(answer.b = question.b)) + (!(answer.c = question.c)) + (!(answer.d = question.d))) * 0.25) AS Score
FROM answer
INNER JOIN
user u ON answer.userID = u.userID
INNER JOIN
question ON answer.questionID = question.questionID
GROUP BY answer.userID
I do not really know if this is possible to do this but I will expose my problem.
I have two tables cases and progress
cases
+----------+--------------+---------------------+---------+------+
| id_cases | name | date_surgery | archive | done |
+----------+--------------+---------------------+---------+------+
| 1 | Cranioplasty | 2016-02-01 00:00:00 | 1 | 0 |
| 2 | Cranioplasty | 2016-02-02 00:00:00 | 0 | 0 |
| 3 | Other | 2016-02-03 00:00:00 | 0 | 0 |
| 4 | Osteotomy | 2016-02-04 00:00:00 | 0 | 0 |
| 5 | Bone Tumor | 2016-02-05 00:00:00 | 1 | 1 |
+----------+--------------+---------------------+---------+------+
progress (which contains thousands of records)
+-------------+---------+---------+---------+
| id_progress | task_id | case_id | current |
+-------------+---------+---------+---------+
| 1 | 103006 | 1 | 0 |
| 2 | 103002 | 1 | 1 |
| 3 | 103003 | 1 | 1 |
| 4 | 201006 | 5 | 0 |
| 5 | 201007 | 5 | 1 |
| .... | ... | ... | ...|
+-------------+---------+---------+---------+
The link between the tables is cases.id_cases = progress.case_id
I want to select all cases with archive and done = 0. I also want to get some progress that are linked to this case
I tought about a condition to select a specific range of task_id related to the result of cases.name.
So basically I want this
SELECT id_cases, name, date_surgery, task_id, current
FROM cases
LEFT JOIN progress on progress.case_id = cases.id_cases
WHERE archive = 0 AND done = 0
But if name is Cranioplasty I just want progress.task_id that are equal to 103006, 103002 and 105002. For Bone Tumor I want 201006, 205003 and 207001. And this for each different name.
There is no logic between the id_cases and the task_id. I must hardcode this.
I tried differents things but none suceeded
SELECT id_Cases, name, date_surgery, task_id, current
from cases
left join progress on progress.case_id = cases.id_cases
where archive = 0 and done = 0
and case when name='Cranioplasty' then task_id=103006 and task_id=103002 else
case when name='Bone Tumor' then task_id=201006 else
case when name='Osteotomy' then task_id=301002 else
case when name='MBIO' then task_id=401006 end end end end
order by name, date_surgery
In fine I try to get this result (task_id is not important, I just want to result of current)
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
| case | name | date_surg | task_1 | 1_res | task_2 | 2_res | task_3 | 3_res |
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
| 1 | Cranioplasty | date | 103006 | 0 | 103002 | 0 | 105002 | 1 |
| 1 | Cranioplasty | date | 103006 | 1 | 103002 | 1 | 105002 | 0 |
| 1 | Cranioplasty | date | 103006 | 1 | 103002 | 0 | 105002 | 1 |
| 2 | Cranioplasty | date | 103006 | 0 | 103002 | 1 | 105002 | 0 |
| 2 | Cranioplasty | date | 103006 | 1 | 103002 | 0 | 105002 | 1 |
| 2 | Cranioplasty | date | 103006 | 0 | 103002 | 1 | 105002 | 1 |
| 3 | Bone Tumor | date | 201006 | 1 | 205003 | 0 | 205005 | 0 |
| 3 | Bone Tumor | date | 201006 | 0 | 205003 | 1 | 205005 | 1 |
| ... | | | | | | | | |
+------+--------------+-----------+--------+-------+--------+-------+--------+-------+
PS : I just put my table as an example to help understanding the problem. It does not includes all the records
I know that I can use temporary or virtual table but I wanted to know how to resolve this with only a query
Well, anyway its bad practice to hardcode this relations between name and task id. You need to store them in database or smthng. So you can join that table and do it in 1 query.
If you cant or dont want to its better to save them atleast to an array so you can dynamically generate query part with this conditions if its possible.
select
a.id_cases,
a.name,
b.task_id,
b.current
from
cases a
left join
progress b ON b.case_id = a.id_cases
where
a.archive = 0
and a.done = 0
and (
(b.task_id in (103006,103002,105002) and a.name = 'Cranioplasty')
OR (b.task_id in (201006,205003,207001) and a.name = 'Bone Tumor')
)
If you can use any language to generate this part
and (
(b.task_id in (103006,103002,105002) and a.name = 'Cranioplasty')
OR (b.task_id in (201006,205003,207001) and a.name = 'Bone Tumor')
)
Do it. For example in php
foreach($arRealtions as $name => $taskIDs)
{
$query .= '(b.task_id in ('.implode(',',$taskIDs).') and a.name = "'.$name.'")';
}
I have 2 tables bellow
0 --> Pending
1 --> Success
2 --> Fail
table : mntnc
+-------+-------+-------+
| id | own | sts |
+-------+-------+-------+
| 1 | BN | 1 |
| 2 | BB | 2 |
| 3 | BN | 1 |
| 4 | BD | 1 |
| 5 | BD | 0 |
table : istlsi
+-------+-------+-------+
| id | own | sts |
+-------+-------+-------+
| 1 | BN | 1 |
| 2 | BB | 1 |
| 3 | BB | 1 |
| 4 | BC | 0 |
| 5 | BD | 2 |
of the two tables above, I want to add both of them to be the table below
+-------+-----------+-----------+-----------+
| own | success | fail | pending |
+-------+-----------+-----------+-----------+
| BN | 3 | 0 | 0 |
| BB | 2 | 1 | 0 |
| BD | 1 | 1 | 1 |
| BC | 0 | 0 | 1 |
The two key points here:
Union tables (I aliased result to B)
Use sum(case...) for each column.
First we union both tables together as an inline view.
We then use a case statement for each desired column and evaluate the status setting the value to 1 or 0 depending on sts value. and then sum those...
SELECT own
, sum(case when sts=1 then 1 else 0 end) as Success
, sum(case when sts=2 then 1 else 0 end) as Fail
, sum(case when sts=0 then 1 else 0 end) as Pending
FROM ( SELECT ID, own, sts
FROM mntnc
UNION ALL
SELECT id, own, sts
FROM istlsi
) B
GROUP BY own
I have two tables.
TABLE A
ID | LABEL|PARENT_ID| VISIBLE | HIDEABLE
1 |SPORTS| 1 | 1 | 1
2 | FOOD | 1 | 1 | 0
3 | CARS | 1 | 0 | 1
4 |TRAVEL| 1 | 1 | 1
5 | LOVE | 1 | 1 | 1
6 | OTHER| 1 | 1 | 0
7 | SHOES| 3 | 0 | 1
8 |TRAVEL| 3 | 1 | 1
9 |NATURE| 3 | 1 | 1
10 |FRIEND| 3 | 1 | 0
11 | CARS | 3 | 0 | 1
12 | LOVE | 3 | 1 | 1
TABLE B
ID | LABEL|PARENT_ID| DISPLAY_POST | DISPLAY_COMMENTS
1 |SPORTS| 1 | 1 | 1
2 | FOOD | 1 | 1 | 0
3 | CARS | 1 | 0 | 1
4 |TRAVEL| 3 | 1 | 1
I want to insert data into TABLE B from TABLE A with these checks:
A.LABEL <> B.LABEL AND A.VISIBLE=1 AND A.HIDEABLE=1
How can I do this?
Everything I try it returns duplicates or missing rows.
Just use insert . . . select with the right conditions:
insert into b( . . .)
select . . .
from a
where a.visible = 1 and a.hideable = 1 and
not exists (select 1 from b2 where a.label = b2.label);
The . . . are just the list of columns for inserting.
This query looks like have logical error so doesnt give what i want exactly. I hope i explained clearly below. Could you help me please?
SELECT a.CreateBy, CreateDate,
(SELECT COUNT(*) FROM MyTable WHERE Item1=1) as Item1Count,
(SELECT COUNT(*) FROM MyTable WHERE Item1=2) as Item2Count,
(SELECT COUNT(*) FROM MyTable WHERE Item1=3) as Item3Count
FROM MyTable a;
MyTable
Id | CreateBy | CreateDate | Item1 | Item2 | Item3
-----------------------------------------------------
100 | John | 01.06.2015 | 1 | 0 | 1
101 | John | 01.06.2015 | 1 | 1 | 1
102 | Ahn | 01.06.2015 | 0 | 1 | 0
103 | Patrick | 01.06.2015 | 1 | 1 | 0
104 | John | 02.06.2015 | 1 | 0 | 1
I want to get data like below.
CreateBy | CreateDate | Item1Count | Item2Count | Item3Count
------------------------------------------------------------
John | 01.06.2015 | 2 | 1 | 2
John | 02.06.2015 | 1 | 0 | 1
Patrick | 01.06.2015 | 1 | 1 | 0
Ahn | 01.06.2015 | 0 | 1 | 0
You can use conditional sum and then group by something as
select
CreateBy,
CreateDate,
sum(Item1=1) as Item1Count,
sum(Item2=1) as Item2Count,
sum(Item3=1) as Item3Count
from MyTable
group by CreateBy,CreateDate