I have a table with the structure
CREATE TABLE `old_reminder` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`applicant_id` int(11) NOT NULL,
`date` datetime NOT NULL,
`type` enum('payment_15_min','payment_1_day','payment_3_day') NOT NULL DEFAULT 'payment_15_min',
PRIMARY KEY (`id`)
)
and I want to migrate its data to another table with the structure
CREATE TABLE `new_reminders` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`payment_reminder_1_count` int(11) DEFAULT NULL,
`payment_reminder_1_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
)
basically multiple rows for each user_id will be converted into 1 row with all the enum values as columns.
I have tried the following but it is updating only 1 row
UPDATE reminders
INNER JOIN old_reminder AS `old`
ON user_id = old.applicant_id
SET new_reminder_1_date = IF(old.type = 'payment_15_min' OR old.type = 'payment_1_day' OR old.type = 'payment_3_day', old.date, '2018-01-01 00:00:00'),
payment_reminder_1_count = IF(old.type = 'payment_15_min' OR old.type = 'payment_1_day' OR old.type = 'payment_3_day',
CASE
WHEN old.type = 'payment_15_min' THEN 1
WHEN old.type = 'payment_1_day' THEN payment_reminder_1_count + 1
WHEN old.type = 'payment_3_day' THEN payment_reminder_1_count + 1 END, 0)
WHERE applicant_id = 123;
If you model looks like this
truncate table old_reminder;
insert into old_reminder (applicant_id,date,type) values (123,'2018-01-01','payment_15_min');
insert into old_reminder (applicant_id,date,type) values (123,'2018-01-02','payment_1_day');
truncate table new_reminders;
insert into new_reminders(user_id,payment_reminder_1_date) values (123,'2016-01-01');
Then a simplified version of your query
update new_reminders n join (select * from old_reminder order by applicant_id,`date`) old on old.applicant_id = n.user_id
SET
enumstr = old.type,
payment_reminder_1_date =
case
when old.type in ('payment_15_min','payment_1_day','payment_3_day') then old.date
else '2017-01-01'
end
WHERE applicant_id = 123;
Produces this result which I think is what you mean by it is updating only 1 row
+----+---------+--------------------------+-------------------------+----------------+
| id | user_id | payment_reminder_1_count | payment_reminder_1_date | enumstr |
+----+---------+--------------------------+-------------------------+----------------+
| 1 | 123 | NULL | 2018-01-01 00:00:00 | payment_15_min |
+----+---------+--------------------------+-------------------------+----------------+
1 row in set (0.00 sec)
The where clause is evaluated last in this query and is free to choose which one it wants from the result set - in this case always the first.
if the query is changed to test test the payment_reminder_1_date
update new_reminders n join (select * from old_reminder order by applicant_id,`date`) old on old.applicant_id = n.user_id
SET
enumstr = old.type,
payment_reminder_1_date =
case
when old.type in ('payment_15_min','payment_1_day','payment_3_day') then old.date
else '2017-01-01'
end
WHERE applicant_id = 123 and n.payment_reminder_1_date <> old.`date`
Then you get something more like what you hope for
+----+---------+--------------------------+-------------------------+---------------+
| id | user_id | payment_reminder_1_count | payment_reminder_1_date | enumstr |
+----+---------+--------------------------+-------------------------+---------------+
| 1 | 123 | NULL | 2018-01-02 00:00:00 | payment_1_day |
+----+---------+--------------------------+-------------------------+---------------+
1 row in set (0.00 sec)
But I don't think this is actually what you are looking for and I would suggest a cursor might be the way forward.
Related
I have table v and t with relation
v (one) -> t (many)
CREATE TABLE `v` (
`i` int NOT NULL,
`status` varchar(255) DEFAULT NULL,
PRIMARY KEY (`i`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `t` (
`i` int NOT NULL,
`v_id` varchar(255) DEFAULT NULL,
`t_status` varchar(255) DEFAULT NULL,
PRIMARY KEY (`i`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO v (i,status) VALUES(1,'default'),(2,'default'),(3,'default');
INSERT INTO t (i,v_id,t_status) VALUES(1,1,'ON'),(2,1,'ON'),(3,1,'OFF')(4,2,'ON'),(5,2,'ON'),(6,3,'ON');
I need to select record from table v if t of v is have status = 'ON' and lock for update status
select * from v where v.i in (select v.i from v join t on v.i = t.v_id where v.status = 'default' group by v.i) limit 1 for update skip locked;
PS.
I need to select from selected due to I don't want to lock table T
Step 1 open session 1
start transaction;
Step 2 select first record for update
mysql> select * from v where v.i in (select v.i from v join t on v.i = t.v_id where v.status = 'default' group by v.i) limit 1 for update skip locked;
+---+---------+
| i | status |
+---+---------+
| 1 | default |
+---+---------+
1 row in set (0.00 sec)
Step 3 create new session (try to be new application instance)
start transaction;
Step 4 update record session one and commit it
update v set status = 'updated' where v.i = 1;
commit;
Step 5 try to select same query with session 2
mysql> select * from v where v.i in (select v.i from v join t on v.i = t.v_id where v.status =
'default' group by v.i) limit 1 for update skip locked;
+---+---------+
| i | status |
+---+---------+
| 1 | updated |
+---+---------+
1 row in set (0.00 sec)
I so confusing why the result is not match the criteria because I need status = default from table v
OR any suggestion for the query, I'm stuck for a while
Thank you for replied.
I am new to MySql large queries, and trying to find some solution for my problem,
I looking for delete duplicate values based on "ID_object" column in my USER_TABLE.
Here is my USER_TABLE description,
`USER_TABLE` (
`ID` varchar(256) NOT NULL,
`ID_OBJECT` varchar(256) DEFAULT NULL,
`INSERTION_TIME` date DEFAULT NULL,
KEY `USER_TABLE_inx01` (`ID`(255)),
KEY `user_inx02` (`ID_OBJECT`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I tried the following query to remove the duplicate ID_OBJECTs,
delete from USER_TABLE where id in (
select ID from USER_TABLE,
(select ID_OBJECT, min(INSERTION_TIME) as fecha from USER_TABLE group by ID_OBJECT having count(ID_OBJECT)>1) tbpr
where USER_TABLE.ID_OBJECT = tbpr.ID_OBJECT and USER_TABLE.INSERTION_TIME=tbpr.fecha);
But it says,
SQL Error (1093): Table 'USER_TABLE' is specified twice, both as a target for 'DELETE' and as a separate source for data
Can anyone assist me in this?
This will do it. I haven't attempted to check whether your actual business logic for removing duplicates is correct, since your stated requirement isn't 100% clear anyway, but this is one way you can overcome the error message:
CREATE TEMPORARY TABLE IF NOT EXISTS duplicates AS (
SELECT UT.id
FROM `USER_TABLE` AS UT
INNER JOIN
(SELECT
ID_OBJECT,
MIN(INSERTION_TIME) AS fecha
FROM `USER_TABLE`
GROUP BY ID_OBJECT
HAVING COUNT(ID_OBJECT)>1) AS tbpr
ON
UT.ID_OBJECT = tbpr.ID_OBJECT AND UT.INSERTION_TIME = tbpr.fecha
);
DELETE FROM `USER_TABLE`
WHERE id IN (SELECT id FROM duplicates);
DROP TABLE IF EXISTS duplicates;
You can see a working demo here: https://www.db-fiddle.com/f/amnAPUftLD1SmW67fjVSEv/0
You could change your query slightly
delete from USER_TABLE
where concat(id_object,insertion_time) in
(
select concat(ID_object,fecha) from
(
select ID_OBJECT, min(INSERTION_TIME) as fecha
from USER_TABLE
group by ID_OBJECT
having count(ID_OBJECT)>1
) tbpr
)
But this would not cope with triplicates, quadruplets etc. so maybe you need to reverse the logic and keep only the max where there are multiples
delete from USER_TABLE
where concat(id_object,insertion_time) not in
(
select concat(ID_object,fecha) from
(
select ID_OBJECT, max(INSERTION_TIME) as fecha
from USER_TABLE
group by ID_OBJECT
having count(ID_OBJECT)>1
) tbpr
)
and
id_object not in
(
select ID_object from
(
select ID_OBJECT, count(*) as fecha
from USER_TABLE
group by ID_OBJECT
having count(ID_OBJECT) = 1
) tbpr2
)
;
create table `USER_TABLE` (
`ID` varchar(256) NOT NULL,
`ID_OBJECT` varchar(256) DEFAULT NULL,
`INSERTION_TIME` date DEFAULT NULL,
KEY `USER_TABLE_inx01` (`ID`(255)),
KEY `user_inx02` (`ID_OBJECT`(255))
) ;
truncate table user_table;
insert into user_table values
(1,1,'2017-01-01'),(2,1,'2017-01-02'),(3,1,'2017-01-03'),
(4,2,'2017-01-01');
Result of first query
MariaDB [sandbox]> select * from user_table;
+----+-----------+----------------+
| ID | ID_OBJECT | INSERTION_TIME |
+----+-----------+----------------+
| 2 | 1 | 2017-01-02 |
| 3 | 1 | 2017-01-03 |
| 4 | 2 | 2017-01-01 |
+----+-----------+----------------+
3 rows in set (0.00 sec)
Result of second query
MariaDB [sandbox]> select * from user_table;
+----+-----------+----------------+
| ID | ID_OBJECT | INSERTION_TIME |
+----+-----------+----------------+
| 3 | 1 | 2017-01-03 |
| 4 | 2 | 2017-01-01 |
+----+-----------+----------------+
2 rows in set (0.00 sec)
I want to create a query in MySQL, on an order table and verify if it has a booking id, if it does not have a booking_id it should available on all relations in the invoice table.
I want the value returned to be a boolean in a single field.
Taken the example given, in
Case of id #1 I expect an immediate true, because it's available
Case of id #2 I expect an "delayed" false from the invoice table as not all related invoices have an booking_id, it should only return true if invoice id #3 actually has an booking id, meaning all invoices have an booking_id when the order does not.
I've tried several ways but still failed and don't even know what the best way to tackle this is.
Thanks for your input in advance!
Table order:
|----+------------+
| id | booking_id |
|----+------------+
| 1 | 123 |
| 2 | NULL |
|----+------------+
Table invoice:
+----+----------+------------+
| id | order_id | booking_id |
+----+----------+------------+
| 1 | 1 | 123 |
| 2 | 2 | 124 |
| 3 | 2 | NULL |
+----+----------+------------+
Schema
CREATE TABLE IF NOT EXISTS `invoice` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`booking_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`booking_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
If I understand you correctly, this is the base query for your request:
SELECT
O.id
, SUM(CASE WHEN I.booking_id IS NOT NULL THEN 1 ELSE 0 END) AS booked_count
, COUNT(1) AS total_count
, CASE WHEN SUM(CASE WHEN I.booking_id IS NOT NULL THEN 1 ELSE 0 END) = COUNT(1) THEN 1 ELSE 0 END AS has_all_bookings
FROM
`order` O
LEFT JOIN invoice I
ON O.id = I.order_id
GROUP BY
O.id
If you want to check if there is no record in the invoice table add the COUNT(1) to the last CASE statement as an additional condition (COUNT(1) = 0)
Fiddle Demo
I have not understood how the logic works out when the order is booked but some of the invoices are not. I'll presume either is good for a true value (OR logic). I'd avoid COUNT and GROUP BY and go for a SUBSELECT, which works fine in MySQL (I'm using and old 5.1.73-1 version).
This query gives you both values in distinct columns:
SELECT o.*
, (booking_id IS NOT NULL) AS order_booked
, (NOT EXISTS (SELECT id FROM `invoice` WHERE order_id=o.id AND booking_id IS NULL)) AS invoices_all_booked
FROM `order` o
Of course you can combine the values:
SELECT o.*
, (booking_id IS NOT NULL OR NOT EXISTS (SELECT id FROM `invoice` WHERE order_id=o.id AND booking_id IS NULL)) AS booked
FROM `order` o
Here you go, create a view that does it
create view booked_view as
select `order`.id as order_id
,
case when booking_id > 0 then true
when exists (SELECT id FROM invoice WHERE order_id=`order`.id AND invoice.booking_id IS NULL) then true
else false
end as booked
from `order` ;
Then just join your view to the order table and you will have your boolean column 'booked'
select o.id, booked from `order` o
join booked_view on (o.id = booked_view.order_id)
I have two tables with data
CREATE TABLE `MASTER` (
`NAME` VARCHAR(10) NOT NULL,
`QTY` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`NAME`)
);
NAME | QTY
----------
'ABC' | 0
'XYZ' | 0
CREATE TABLE `DETAIL` (
`NAME` VARCHAR(10) NOT NULL,
`QTY` INT(10) UNSIGNED NOT NULL,
`FLAG` TINYINT(1) UNSIGNED NOT NULL
);
NAME | QTY| FLAG
--------------------
'ABC' | 10 | 0
'ABC' | 20 | 0
'PQR' | 15 | 0
'PQR' | 25 | 0
i want to update sum(detail.qty) to master and set its flag to 1
so i have written query
UPDATE MASTER M, DETAIL D
SET M.QTY = M.QTY + D.QTY,
D.FLAG =1
WHERE M.NAME = D.NAME;
i have guesed MASTER.QTY should be 30 (10 + 20) from detail table.
but it only updates the first value
actual value is MASTER.QTY =10 (only updtaed first value from table)
How can i get MASTER.QTY =30?
Try this query:
update `MASTER` m,`DETAIL` d,
(
SELECT `NAME`, SUM( `QTY` ) as `QTY`
FROM `DETAIL`
GROUP BY `NAME`
) s
SET m.QTY = s.QTY,
d.FLAG = 1
WHERE
m.NAME = s.NAME
AND m.NAME = d.NAME
;
SQLFiddle demo --> http://www.sqlfiddle.com/#!2/ab355/1
IMO, your Master table is unnecessary. You don't need it if the amount of rows ain't in a > 5-digit range.
This equals the MASTER table:
SELECT NAME, SUM(QTY), FLAG FROM DETAIL GROUP BY NAME;
You can create a view from that easily.
Your answer anyways:
UPDATE MASTER m
JOIN DETAIL d ON m.NAME = d.NAME
SET
d.FLAG = 1,
m.QTY = (SELECT SUM(QTY) FROM DETAIL WHERE NAME = d.NAME GROUP BY NAME)
WHERE m.NAME = d.NAME
Also, always follow normalization rules: https://en.wikipedia.org/wiki/Database_normalization
I have a posts/comments database that I am unable to order correctly.
I need it to be ordered primarily by its id but if its parent_id does not equal its id, it is placed after its parent and also these children would ordered by id.
Here is my current database.
CREATE TABLE `questions` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`parent_id` int(10) NOT NULL,
`entry_type` varchar(8) NOT NULL,
`entry_content` varchar(1024) NOT NULL,
`entry_poster_id` varchar(10) NOT NULL,
`entry_status` varchar(1) NOT NULL,
`entry_score` varchar(10) NOT NULL,
`time_posted` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;
--
-- Dumping data for table `questions`
--
INSERT INTO `questions` VALUES(1, 1, 'question', 'How do I does SQL?', 'CodyC', '0', '2', '1308641965');
INSERT INTO `questions` VALUES(2, 1, 'answer', 'Easy, you eat cheese!', 'PatrickS', '0', '-4', '1308641965');
INSERT INTO `questions` VALUES(3, 2, 'comment', 'WTF are you on noobass?!', 'FraserK', '0', '100', '1308641965');
INSERT INTO `questions` VALUES(4, 1, 'answer', 'blah', '5', '0', '0', '1308642204');
INSERT INTO `questions` VALUES(5, 4, 'comment', 'blah2', '4', '0', '0', '1308642247');
INSERT INTO `questions` VALUES(6, 2, '2', '3', '3', '3', '3', '3');
and my current query
SELECT *
FROM questions
WHERE parent_id =1
OR parent_id
IN (
SELECT id
FROM questions
WHERE parent_id =1
AND parent_id != id
)
how do I order so that order id to that each object comes after its parent, where the id = parent_id means is a base level and has no parent?
This seems to work:
SELECT *
FROM questions
order by case when parent_id != id then parent_id else id end, id;
But it depends whether you want grandchildren before children etc. Your question doesn't specify.
However, if you use this technique you can make your ordering term(s) as complicated as you like - it doesn't need to be a selected column - just make up what you need.
Looks a bit complicated with mysql, but you can use PHP for it. Use recursive function. This will be easy to handle.
here is a function from code bank. It simply creates a unorder list tree. You can modify it to suit your requirments
function output_lis_pages($parentID = 0)
{
$stack = array(); //create a stack for our <li>'s
$arr = array();
$sql = "select pageid, pagetitle, pagelink, parentid
from pages
where parentid = $parentID
order by orderid";
$crs = mysql_query($sql);
if(mysql_num_rows($crs)==0)
{
// no child menu exists for this page
return false;
}
else
{
while($crow = mysql_fetch_array($crs))
{
$arr [] = array(
'pagetitle'=> stripslashes($crow["pagetitle"]),
'pagelink'=> $crow["pagelink"],
'parentid'=>$crow["parentid"],
'pageid'=>$crow["pageid"]
);
}
}
foreach($arr as $a)
{
$str = '';
//if the item's parent matches the parentID we're outputting...
if($a['parentid']==$parentID)
{
if($a['pagelink']=="")
$tmplink = "page.php?pageid=".$a['pageid'];
else
$tmplink = $a['pagelink'];
$str.='<li>'.$a['pagetitle']."";
$subStr = output_lis_pages($a['pageid']);
if($subStr){
$str.="\n".'<ul>'.$subStr.'</ul>'."\n";
}
$str.='</li>'."\n";
$stack[] = $str;
}
}
//If we have <li>'s return a string
if(count($stack)>0)
{
return join("\n",$stack);
}
//If no <li>'s in the stack, return false
return false;
}
SELECT *
, CASE WHEN parent_id = 1 THEN id ELSE parent_id END AS sort_level
FROM questions
WHERE parent_id = 1
OR parent_id
IN (
SELECT id
FROM questions
WHERE parent_id = 1
AND parent_id != id
)
ORDER BY sort_level
, id
You've run into the old bugbear of relational database systems. They aren't fun to work with when your data is hierarchic. You have the issue of trying to produce what is really a particular walk of a graph from database records. That is tough without recursive features in your SQL dialect. Here is a link that might help:
http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/
See also, on StackOverflow: What are the options for storing hierarchical data in a relational database?
After a week of trying i could not get it to work with the query, so i decided just to do it in PHP, this will also reduce load off the MySQL engine. Here is my php for anyone that wishes to reference it.
$question_id = $database->escape_string($question_id); //escape input
$q = "SELECT * FROM questions WHERE parent_id = $question_id OR parent_id IN (SELECT id FROM questions WHERE parent_id = $question_id AND parent_id != id) ORDER BY parent_id , id";
$database->dbquery($q);//query the DB
while($row = $database->result->fetch_assoc()){//Process results to standard array.
//other irrelevant stuff happens here
$unsorted[] = $row;
}
$question = array_shift($unsorted);//take the question off the array
$sorted[] = $question;//add it to the start of the sorted array
$qusetion_id = $question['id'];
foreach($unsorted as $row){//this creates a multidimensional hierarchy of the answers->comments
if($row['parent_id'] == $question_id){//if its an answer
$sorted_multi[$row['id']] = array();//create a new answer sub-array
$sorted_multi[$row['id']][] = $row;//append it
}else{
$sorted_multi[$row['parent_id']][] = $row;//append the answer to the correct sub-array
}
}
foreach($sorted_multi as $temp){//converts the multidimensional into a single dimension appending it to the sorted array.
foreach($temp as $row){
$sorted[] = $row;
}
}
Tedious yes, but it works out better in the end because of other unforeseen processing that needs to be done post-mysql.
Thanks for all the responses though :):):)
looking into your question and reading your comment - "i need to get ONE specific question, with ALL the answers and comments", I think you are looking to show every question followed by its answer followed by its comments. Right?
And if so, this is your query:
SELECT `id`,
(CASE
WHEN `entry_type` = 'question' THEN CONCAT(`id`, '-', `parent_id`)
WHEN `entry_type` = 'answer' THEN CONCAT(`id`, '-', `parent_id`)
WHEN `entry_type` = 'comment' THEN CONCAT(`parent_id`, '-', `id`)
END) `sort_order`,
`entry_type`, `entry_content`
FROM `questions`
ORDER BY `sort_order`;
The above query will give you every question, followed by its first answer, followed by the comments to its first answer; then the second answer, followed by the comments to the second answer and so on.
So for the INSERTs that you had given, this will be the output:
+----+------------+------------+--------------------------+
| id | sort_order | entry_type | entry_content |
+----+------------+------------+--------------------------+
| 1 | 1-1 | question | How do I does SQL? |
| 2 | 2-1 | answer | Easy, you eat cheese! |
| 3 | 2-3 | comment | WTF are you on noobass?! |
| 6 | 2-6 | comment | 3 |
| 4 | 4-1 | answer | blah |
| 5 | 4-5 | comment | blah2 |
+----+------------+------------+--------------------------+
Hope it helps.
EDIT: Updated query to fetch answers and comments for only ONE question
SELECT `id`,
(CASE
WHEN (`entry_type` IN ('question', 'answer')) THEN `id`
WHEN `entry_type` = 'comment' THEN `parent_id`
END) `sort_order_1`,
(CASE
WHEN (`entry_type` IN ('question', 'answer')) THEN `parent_id`
WHEN `entry_type` = 'comment' THEN `id`
END) `sort_order_2`,
(CASE
WHEN (`entry_type` IN ('question', 'answer')) THEN `parent_id`
WHEN `entry_type` = 'comment' THEN (SELECT `Q1`.`parent_id` FROM `questions` `Q1` WHERE `Q1`.`id` = `Q`.`parent_id`)
END) `question_id`,
`entry_type`, `entry_content`
FROM `questions` `Q`
HAVING `question_id` = 1
ORDER BY `sort_order_1`, `sort_order_2`;
OUTPUT:
+----+--------------+--------------+-------------+------------+--------------------------+
| id | sort_order_1 | sort_order_2 | question_id | entry_type | entry_content |
+----+--------------+--------------+-------------+------------+--------------------------+
| 1 | 1 | 1 | 1 | question | How do I does SQL? |
| 2 | 2 | 1 | 1 | answer | Easy, you eat cheese! |
| 3 | 2 | 3 | 1 | comment | WTF are you on noobass?! |
| 6 | 2 | 6 | 1 | comment | 3 |
| 4 | 4 | 1 | 1 | answer | blah |
| 5 | 4 | 5 | 1 | comment | blah2 |
+----+--------------+--------------+-------------+------------+--------------------------+
You can change the HAVING part to fetch answers and comments for a specific question. Hope this helps!
EDIT 2: another possible implementation might be (but I think it might have some performance implications for large tables):
SELECT `a`.`id` AS `question_id`, `a`.`entry_content` AS `question`,
`b`.`id` AS `answer_id`, `b`.`entry_content` AS `answer`,
`c`.`id` AS `comment_id`, `c`.`entry_content` AS `comment`
FROM `questions` `a`
LEFT JOIN `questions` `b` ON (`a`.`id` = `b`.`parent_id` AND `b`.`entry_type` = 'answer')
LEFT JOIN `questions` `c` ON (`b`.`id` = `c`.`parent_id` AND `c`.`entry_type` = 'comment')
WHERE `a`.`entry_type` = 'question'
AND `a`.`id` = 1
ORDER BY `a`.`id`, `b`.`id`, `c`.`id`;
OUTPUT:
+----+--------------------+------+-----------------------+------+--------------------------+
| id | question | id | answer | id | comment |
+----+--------------------+------+-----------------------+------+--------------------------+
| 1 | How do I does SQL? | 2 | Easy, you eat cheese! | 3 | WTF are you on noobass?! |
| 1 | How do I does SQL? | 2 | Easy, you eat cheese! | 6 | 3 |
| 1 | How do I does SQL? | 4 | blah | 5 | blah2 |
+----+--------------------+------+-----------------------+------+--------------------------+
Simply use the "ORDER BY" clause to select the ordering you want!
SELECT *
FROM questions
WHERE parent_id =1
OR parent_id
IN (
SELECT id
FROM questions
WHERE parent_id =1
AND parent_id != id
)
ORDER BY Parent_id , id