best way to display value from mysql inner join - php

I haven't been coding for a while, and i started a new project lately.
In that project, i need to make a very simple inner join to associate values from 2 tables:
table questions:
id | question | order
1 | how? | 1
2 | what? | 2
3 | when? | 3
table answers:
id_question | answer | order
1 | this way | 1
1 | that way | 2
2 | this | 1
2 | that | 2
3 | now | 1
3 | later | 2
How can I correctly get the questions and related answers, and display them, ordered by order?
I did this:
SELECT id, question, Q.order as qorder, id_question, answer, A.order as aorder FROM questions as Q INNER JOIN answers as A ON Q.id = A.id_question ORDER BY qorder
which result in this:
id | question | qorder | id_question | answer | aorder
1 | how? | 1 | 1 | this way | 1
1 | how? | 1 | 1 | that way | 2
2 | what? | 2 | 2 | this | 1
2 | what? | 2 | 2 | that | 2
3 | when? | 3 | 3 | now | 1
3 | when? | 3 | 3 | later | 2
DISPLAYING RESULTS:
$same_id = -1;
while ( $poll = $qa -> fetch() ) {
if ($poll['id'] == $same_id ) {
echo '<li>'.$poll['answer'].'</li>';
}
else {
if ( $poll['id'] == $same_id+1 ) { echo '</ul>'; }
echo '<ul>'.$poll['question'];
echo '<li>'.$poll['answer'].'</li>';
$same_id = $poll['id'];
}
echo '</ul>';
}
which display:
<ul>How?
<li>this way</li>
<li>that way</li>
</ul>
<ul>What?
<li>this</li>
<li>that</li>
</ul>
<ul>When?
<li>now</li>
<li>later</li>
</ul>
it all works out, but it doesn't feel right.
First, I have the answers ordered by "luck", without specifying it in the request.
And then, the code feels too "complicated" for what it is.
I feel there is a better and cleaner way to do this kind of work.

You can simply use the aorder to order explicitly:
SELECT ...
FROM ...
INNER JOIN ...
ORDER BY
qorder ASC,
aorder ASC
Your code to display is alright. It could be improved by using PDOStatement::fetchAll() and foreach, but this is personal taste/preference.
$polls = $qa->fetchAll();
foreach($polls as $poll) {
// output question and answers
}

Related

Shortening PHP code when comparing multiple MYSQL columns

I use lengths of code similar to this repeatedly in my scripting because I cannot find a shorter way to to compare the MYSQL columns
if ($them['srel1']=="Y" AND $me['Religion']=='Adventist'){$seek11pts=5;}
if ($them['srel2']=="Y" AND $me['Religion']=='Agnostic'){$seek11pts=5;}
if ($them['srel3']=="Y" AND $me['Religion']=='Atheist'){$seek11pts=5;}
if ($them['srel4']=="Y" AND $me['Religion']=='Baptist'){$seek11pts=5;}
if ($them['srel5']=="Y" AND $me['Religion']=='Buddhist'){$seek11pts=5;}
if ($them['srel6']=="Y" AND $me['Religion']=='Caodaism'){$seek11pts=5;}
if ($them['srel7']=="Y" AND $me['Religion']=='Catholic'){$seek11pts=5;}
if ($them['srel8']=="Y" AND $me['Religion']=='Christian'){$seek11pts=5;}
if ($them['srel9']=="Y" AND $me['Religion']=='Hindu'){$seek11pts=5;}
if ($them['srel10']=="Y" AND $me['Religion']=='Iskcon'){$seek11pts=5;}
if ($them['srel11']=="Y" AND $me['Religion']=='Jainism'){$seek11pts=5;}
if ($them['srel12']=="Y" AND $me['Religion']=='Jewish'){$seek11pts=5;}
if ($them['srel13']=="Y" AND $me['Religion']=='Methodist'){$seek11pts=5;}
if ($them['srel14']=="Y" AND $me['Religion']=='Mormon'){$seek11pts=5;}
if ($them['srel15']=="Y" AND $me['Religion']=='Moslem'){$seek11pts=5;}
if ($them['srel16']=="Y" AND $me['Religion']=='Orthodox'){$seek11pts=5;}
if ($them['srel17']=="Y" AND $me['Religion']=='Pentecostal'){$seek11pts=5;}
if ($them['srel18']=="Y" AND $me['Religion']=='Protestant'){$seek11pts=5;}
if ($them['srel19']=="Y" AND $me['Religion']=='Quaker'){$seek11pts=5;}
if ($them['srel20']=="Y" AND $me['Religion']=='Scientology'){$seek11pts=5;}
if ($them['srel21']=="Y" AND $me['Religion']=='Shinto'){$seek11pts=5;}
if ($them['srel22']=="Y" AND $me['Religion']=='Sikhism'){$seek11pts=5;}
if ($them['srel23']=="Y" AND $me['Religion']=='Spiritual'){$seek11pts=5;}
if ($them['srel24']=="Y" AND $me['Religion']=='Taoism'){$seek11pts=5;}
if ($them['srel25']=="Y" AND $me['Religion']=='Wiccan'){$seek11pts=5;}
if ($them['srel26']=="Y" AND $me['Religion']=='Other'){$seek11pts=5;}
EG: if ($them['srel1']=="Y" AND $me['Religion']=='Adventist'){$seek11pts=5;}
I check to seek if the MYSQL column srel1 has a value of Y. if it does then I check to see if the column Religion equals Adventist. If both are true then $seek11pts=5, if they are not both true then nothing happens.
There are 26 srel type columns with either a Y value or null. There are also 26 different values for Religion as you may see. This is but one section of my code. I have multiple HUGE code groupings like this and I'd love to be able to reduce it down to a few lines. I was thinking some kind of array for the religions and another for the numerical endings of the srel columns but I cant get it.
For this current code you can use this:
<?php
$religions = array(1 => 'Adventist','Agnostic','Atheist','Baptist','Buddhist','Caodaism','Catholic','Christian','Hindu','Iskcon','Jainism','Jewish','Methodist','Mormon','Moslem','Orthodox','Pentecostal','Protestant','Quaker','Scientology','Shinto','Sikhism','Spiritual','Taoism','Wiccan','Other');
$count = count($religions) + 1;
for ($i = 1; $i < $count; $i++) {
if ($them["srel$i"]=="Y" && $me['Religion']==$religions[$i]) {
$seek11pts=5;
break;
}
}
While there are ways to accomplish what you ask, you should instead seriously consider restructuring your data.
Better data structure
If your data had a structure more similar to the following:
db.person
+----+------+
| id | name |
+----+------+
| 1 | Nick |
| 2 | Bob |
| 3 | Tony |
+----+------+
PrimaryKey: id
db.religion
+----+---------+
| id | name |
+----+---------+
| 1 | Atheist |
| 2 | Jainism |
| 3 | FSM |
+----+---------+
PrimaryKey: id
db.person_religion
+--------+----------+
| person | religion |
+--------+----------+
| 1 | 2 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
+--------+----------+
UniqueIndex: (person,religion)
...everything you're trying to do could be done with simple queries.
SELECT me.id, me.name, meR.name as religion, count(them.id) as matches
FROM person me
LEFT INNER JOIN person_religion meRlookup
ON me.id = meRlookup.person
LEFT INNER JOIN religion meR
ON meRlookup.religion = meR.id
LEFT INNER JOIN person_religion themRlookup
ON meRlookup.religion = themRlookup.religion
LEFT INNER JOIN person them
ON themRlookup.person = them.id
GROUP BY meR.id
I would recommend using laravel or lumen, since these include a "queries generator" that just write a little code (NOTHING SQL) to make queries and that ..

MySQL: Link answers to comments, grouped and limited

I got the following MySQL table:
+----+--------+------+
| id | answer | type |
+----+--------+------+
>| 1 | -1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
>| 4 | -1 | 2 |
| 5 | 4 | 2 |
| 6 | 4 | 1 |
>| 7 | -1 | 1 |
| 8 | 7 | 2 |
>| 9 | -1 | 2 |
>| 10 | -1 | 1 |
>| 11 | -1 | 2 |
+----+--------+------+
> = original comment
The entries with answer = -1 are the original comments.
The entries with answer != -1 are answers to the comment with the respective id.
Furthermore there are types of comments (in this case 1 or 2).
Now I want to retrieve the original comments (for a specified type and a specified limit) and their answers (type and limit do not matter). Further it would be great to group the result by the two types (again, only the original comment's type matters for grouping).
A query result for type=1 and limit=2 should look like that (not grouped yet):
+----+--------+------+
| id | answer | type |
+----+--------+------+
>| 1 | -1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
>| 7 | -1 | 1 |
| 8 | 7 | 2 |
+----+--------+------+
I have tried several kinds of queries for hours now, can I implement it without a procedure? What would the procedure look like?
I would appreciate your help a lot.
Use a subquery to get 2 original comments of type-1 first, then join the table again to get both original comments and responses.
select b.*
from (
select id
from answers
where type = 1 and answer = -1
limit 2) a
join answers b on a.id = b.id or a.id = b.answer;
fiddle
To select 2 original comments of each type, you'll need to use user-defined-variable to index each original comment. The following code indexes the first original comment as 1, the second one as 2, and so on, then resets to 1 when the type changes. Finally in the final where statement filter out indices greater than 2.
select b.*, a.idx
from (
select id, #idx:=if(#type=a.type,#idx+1,1) idx, #type:=a.type
from (select id, type from answers2 where answer is null order by type) a
join (select #type:=null, #idx:=null) b) a
join answers2 b on a.id = b.id or a.id = b.answer
where a.idx <= 2;
fiddle
Store it as a separate column or even a different table if you are worried about too much data duplication. You are overthinking it.

selecting a set of rows with specific record data

I here today with a question that has left me rather confused and puzzled. Perhaps someone out there could give me a bit of assistance.
I have three table as followed. Please note that they are simplified for this question.
//table_checks//
check_id |task_id| status
1 | 1 | Done
2 | 1 | Done
3 | 1 | Done
4 | 2 | Done
5 | 2 | Not Done
6 | 2 | Not Done
7 | 2 | Not Done
8 | 2 | Done
9 | 3 | Done
10 | 3 | Done
11 | 3 | Not Done
12 | 3 | Done
//table_user//
user_id | email | type
1 | a#a.com | IN
2 | b#b.com | IN
3 | c#c.com | EX
//table_chk_usr//
check_id |user_id
1 | 1
2 | 1
3 | 1
4 | 2
5 | 2
6 | 2
7 | 2
8 | 2
9 | 3
10 | 3
11 | 3
12 | 3
Here are three tables with its relation in the table_chk_usr table.
My question is how do I query and select rows of table_user with type 'IN' from table table_user where all of users assigned task_ids in the table_checks are with the status = done.
So the expected result should be as follows
//table_user//
user_id | email | type
1 | a#a.com | IN
Since user_id with 1 has completed all task_ids with status done.
I hope this makes sense to those of you who are reading. Any help will be much appreciated.
Please Note that I am using PHP as my server side language, if that helps in any way.
I think this is what you are looking for.
select user.user_id, user.email, user.type,
sum(if(status = 'done',1, 0)) as done, count(*) as checks
from checks
join chk_user on checks.check_id = chk_user.check_id
join user on chk_user.user_id = user.user_id
group by chk_user.user_id
having done = checks
sqlFiddle
You could use a join here, but there may be a better way to do it.
SELECT * FROM table_checks
INNER JOIN table_chk_usr
ON table_checks.check_id = table_chk_usr.check_id
INNER JOIN table_user
ON table_chk_usr.user_id = table_user.user_id
WHERE table_checks.status = 'Done'
AND table_user.type = 'IN'

PHP MYSQL - ID AS category SUB_ID as Comment

I cant figure out how to get comments underneath mysql db entries..
For example There is one article witch id is 1 and then there are some (for example 3) comments in that article (ID - 1) [ARTICLE_ID][CATEGORY]
And the comments are like: [ID][ARTICLE_ID]
..
so it is like
| ID | SUB_ID | TITLE....
| 1 | 123 | THIS IS A ARTICLE
| 2 | 1 | COMMENT TO ARTICLE 1
| 3 | 1 | COMMENT 2 to article 1
| 4 | 1 | Comment 3 to Article 1
AND CEN_TYPE for all of thesese IDs, 1,2,3,4 is forumentry
I've tryed like this:
SELECT everthing from CNT_Entries_A WHERE CEN_TYPE is like forumentry - so everthing is fine here, but it doesnt put comments underneath (logically)
Putting all ID's AND SUB_ID's in to a array's
making foreach cycle, inside that checking if current ID is equal to arrays value if it is, check if that ID is in array - if is not then printing it out and putting it to an array..
SAME THING to SUB ID
I highly recommend to split the data into two data tables:
Articles
article_id | text
Comments
comment_id | article_id | comment
Then You won't have problem to do a simple SELECT + LEFT JOIN query...
This will give result as article and their comments so that u can then loop over:
find the implementation here
SELECT c1 . * , c2 . *
FROM comments AS c1
JOIN comments AS c2 ON ( c1.id = c2.sub_id
AND c1.id != c2.id )
WHERE c1.cen_type = 'forumentry'
+----+--------+-------------------+------------+----+--------+----------------------+------------+
| id | sub_id | title | cen_type | id | sub_id | title | cen_type |
+----+--------+-------------------+------------+----+--------+----------------------+------------+
| 1 | 1 | THIS IS A ARTICLE | forumentry | 2 | 1 | COMMENT TO ARTICLE 1 | forumentry |
| 1 | 1 | THIS IS A ARTICLE | forumentry | 3 | 1 | COMMENT 2 to article | forumentry |
| 1 | 1 | THIS IS A ARTICLE | forumentry | 4 | 1 | Comment 3 to Article | forumentry |
+----+--------+-------------------+------------+----+--------+----------------------+------------+

Tree-like structure with 5 branches

+-------+------+-----------+------------+
|user_id| name | parent_id |grandparentID
+----+--------+-----------+-------------+
| 1 | one | NULL | NULL |
| 2 | two | 1 | NULL |
| 3 | three | 1 | 1 |
| 4 | four | 2 | 1 |
| 5 | five | 2 | 2 |
| 6 | six | 2 | 2 |
| 7 | seven | 2 | 2 |
| 8 | eight | 3 | 3 |
| 9 | nine | 3 | 2 |
| 10 | ten | 3 | 1 |
| 11 | eleven | 3 | 2 |
+-------------+-----------+------------+
I want to create a tree structure with the following DB schema
Something like this below
One
|
two______________three______________four______________five______________Six
| | | | |
n1 n2 n3 n4 n5 t1 t2 t3 t4 t5 h1 h2 h3 h4 h4 a1 a2 a3 a4 a5 s1 s2 s3 s4 s5
I wrote the following code
<?php
function display_tree() {
$result = $this->qry("SELECT * FROM users WHERE Parent='?' or Parent ='?';" ,
'in(select id from user_id from users where Parent = "'.$_SESSION['id'].'")', $_SESSION['id']);
echo '<div align="center">'.$_SESSION['name'].'<br></div>';
echo '<div align="center">|</div>';
echo '<div align="center">';
while( $row=mysql_fetch_assoc($result)){
echo "___".$row['name'].$row['user_id'].'';
};
$result1 = $this->qry("SELECT * FROM users where grandParent='".$_SESSION['id']."'");
echo '<br>|<br>';
while( $row1 =mysql_fetch_assoc($result1)){
echo "--".$row1['name'];
}
echo '</div>';
}
?>
This is what it displays
one
|
___two___three
|
--four--five--six--seven--eight--
But I wish to have it in the order up above, not this,
I have read tutorials but they all dwell on right left branching, none seems to touch on my type
Any links to good examples, I'll be glad
Any insight on my problem would also help me alot
I seem to have reached a fix end for me
Thanks in advance.
I would recommend using some kind of plugin like jquery plugin that would build the tree for you here are couple of plugins.
http://jquery.bassistance.de/treeview/demo/
http://www.jqwidgets.com/jquery-widgets-demo/#demos/jqxtree/treebindingtojson.htm
https://github.com/pioz/jquery-tree

Categories