selecting from 6 tables useing JOIN got duplicated value - php

her is the mySql to select the students
$institute = $_POST['institute'];
$sections = $_POST['sections'];
$division = $_POST['division'];
$getSearch = $db->prepare("SELECT
a.name, a.phase, a.setNumber, a.email, a.sudImage, a.activity, a.id AS stud_id,
b.id, b.ins_name,
c.id, c.sec_name,
d.id, d.div_name,
e.id, e.std_id, e.sub_id, e.absence,
f.id, f.sub_name, f.subHour, f.level
FROM student_basic_info AS a
CROSS JOIN institutes AS b ON (a.institute = b.id)
CROSS JOIN ins_sections AS c ON (a.section = c.id)
CROSS JOIN ins_division AS d ON (a.division = d.id)
CROSS JOIN student_absence AS e
CROSS JOIN ins_subjects AS f ON (e.sub_id = f.id)
WHERE a.institute =? AND a.section = ? AND a.division =?
GROUP BY a.id
");
$studSearch = array();
$getSearch->bind_param('iii', $institute, $sections, $division);
if ($getSearch->execute()) {
$results = $getSearch->get_result();
//var_dump($studSearch);
$row_cnt = $results->num_rows;
?>
The Problem is
the results should have 2 rows effected
row one come's out right the second come's duplicated
see the var_dump row one
array (size=1)
0 =>
array (size=17)
'name' => string 'Yousef' (length=6)
'phase' => string 'اعدادي' (length=12)
'setNumber' => int 1234
'email' => string 'johnef' (length=6)
'sudImage' => string '' (length=0)
'activity' => int 0
'stud_id' => int 2
'id' => int 3
'ins_name' => string 'fonon' (length=5)
'sec_name' => string 'فنون مسرح' (length=17)
'div_name' => string 'شعبة مرجانية 10' (length=26)
'std_id' => int 4
'sub_id' => int 3
'absence' => string '1' (length=1)
'sub_name' => string 'فنون تطبيقية' (length=23)
'subHour' => string '2' (length=1)
'level' => string 'المستوي الأول' (length=25)
see the var_dump row two
array (size=2)
0 =>
array (size=17)
'name' => string 'Yousef' (length=6)
'phase' => string 'اعدادي' (length=12)
'setNumber' => int 1234
'email' => string 'johnef' (length=6)
'sudImage' => string '' (length=0)
'activity' => int 0
'stud_id' => int 2
'id' => int 3
'ins_name' => string 'fonon' (length=5)
'sec_name' => string 'فنون مسرح' (length=17)
'div_name' => string 'شعبة مرجانية 10' (length=26)
'std_id' => int 4
'sub_id' => int 3
'absence' => string '1' (length=1)
'sub_name' => string 'فنون تطبيقية' (length=23)
'subHour' => string '2' (length=1)
'level' => string 'المستوي الأول' (length=25)
1 =>
array (size=17)
'name' => string 'Rida Ali' (length=8)
'phase' => string 'ابتدائي' (length=14)
'setNumber' => int 0
'email' => string 'johnef' (length=6)
'sudImage' => string '' (length=0)
'activity' => int 0
'stud_id' => int 7
'id' => int 3
'ins_name' => string 'fonon' (length=5)
'sec_name' => string 'فنون مسرح' (length=17)
'div_name' => string 'شعبة مرجانية 10' (length=26)
'std_id' => int 4
'sub_id' => int 3
'absence' => string '1' (length=1)
'sub_name' => string 'فنون تطبيقية' (length=23)
'subHour' => string '2' (length=1)
'level' => string 'المستوي الأول' (length=25)
I try to put this condition CROSS JOIN student_absence AS e ON (e.std_id = a.id) but it come's out with one row only
try 2 with INNER JOIN
.....<br/>
FROM student_basic_info AS a
INNER JOIN institutes AS b ON (a.institute = b.id)<br/>
.....
results
it coming out correct but it should come out with 2 rows now it's coming out with one row only.
try 2 with LEFT JOIN
SELECT
a.name, a.phase, a.setNumber, a.email, a.sudImage, a.activity, a.id AS stud_id,
b.id, b.ins_name,
c.id, c.sec_name,
d.id, d.div_name,
e.id, e.std_id, e.sub_id, e.absence,
f.id, f.sub_name, f.subHour, f.level
FROM student_basic_info AS a
INNER JOIN institutes AS b ON (a.institute = b.id)
INNER JOIN ins_sections AS c ON (a.section = c.id)
INNER JOIN ins_division AS d ON (a.division = d.id)
LEFT JOIN student_absence AS e ON (e.std_id = a.id)
LEFT JOIN ins_subjects AS f ON (f.id = e.sub_id)
WHERE a.institute =? AND a.section = ? AND a.division =?
GROUP BY a.id
results
it coming out correct

Related

Multiple LEFT Join works correct in mysql but not in php

I tried mutiple LEFT JOIN in mysql it works fine there but however if use the same query in php mysqli object method I am not getting what I get in direct mysql
HERE is the Query in MYSQL
SELECT f.*,o.*,fs.* FROM fruits f
LEFT JOIN orders o ON f.id = o.fruit_id
LEFT JOIN fruit_stock fs ON f.id = fs.f_id
MYSQL RESULT
id name price id fruit_id qty id f_id stock_qty
3 Banana 5 2 3 10 1 3 122
3 Banana 5 4 3 8 1 3 122
2 Apple 3 1 2 3 2 2 322
4 pomegranate 4 3 4 15 3 4 23
5 grape 3 NULLNULL NULL 4 5 12
1 mango 45 NULLNULL NULL NULLNULL NULL
Same query with php
$con1 = new mysqli('***','***','***','***');
$sel_sql = 'SELECT f.*,o.*,fs.* FROM fruits f LEFT JOIN orders o ON f.id = o.fruit_id LEFT JOIN fruit_stock fs ON f.id = fs.f_id';
$result = $con1->query($sel_sql);
var_dump($result);
while($row = $result->fetch_assoc()){
var_dump($row);
}
I just var_dump the $row to see the result. When I see I am not getting id for the 6th row as seen on mysql instead I get null
array (size=7)
'id' => string '1' (length=1)
'name' => string 'Banana' (length=6)
'price' => string '5' (length=1)
'fruit_id' => string '3' (length=1)
'qty' => string '10' (length=2)
'f_id' => string '3' (length=1)
'stock_qty' => string '122' (length=3)
array (size=7)
'id' => string '1' (length=1)
'name' => string 'Banana' (length=6)
'price' => string '5' (length=1)
'fruit_id' => string '3' (length=1)
'qty' => string '8' (length=1)
'f_id' => string '3' (length=1)
'stock_qty' => string '122' (length=3)
array (size=7)
'id' => string '2' (length=1)
'name' => string 'Apple' (length=5)
'price' => string '3' (length=1)
'fruit_id' => string '2' (length=1)
'qty' => string '3' (length=1)
'f_id' => string '2' (length=1)
'stock_qty' => string '322' (length=3)
array (size=7)
'id' => string '3' (length=1)
'name' => string 'pomegranate' (length=11)
'price' => string '4' (length=1)
'fruit_id' => string '4' (length=1)
'qty' => string '15' (length=2)
'f_id' => string '4' (length=1)
'stock_qty' => string '23' (length=2)
array (size=7)
'id' => string '4' (length=1)
'name' => string 'grape' (length=5)
'price' => string '3' (length=1)
'fruit_id' => null
'qty' => null
'f_id' => string '5' (length=1)
'stock_qty' => string '12' (length=2)
array (size=7)
'id' => null
'name' => string 'mango' (length=4)
'price' => string '45' (length=2)
'fruit_id' => null
'qty' => null
'f_id' => null
'stock_qty' => null
I am expecting to get the id from the fruit table(which is 1 and the fruit name is mango) but its returning null.
Not sure why is that happening. Any help?
fruit_stock TABLE
id f_id stock_qty
1 3 122
2 2 322
3 4 23
4 5 12
orders Table
id fruit_id qty
1 2 3
2 3 10
3 4 15
4 3 8
I don't want to care about id in other table I just want the main(fruits) table id and other corresponding whole data from other tables.
You can add alias to your ids or remove the useless ones (optional ones are commented):
$sel_sql = 'SELECT
f.*,
-- o.id as order_id,
o.fruit_id,
o.qty,
-- fs.id as fruit_stock_id,
fs.f_id,
fs.stock_id
FROM fruits f LEFT JOIN orders o ON f.id = o.fruit_id LEFT JOIN fruit_stock fs ON f.id = fs.f_id';
Then you will have only one index id on your array.
You can only have one key with a value of Id so when the query runs it is first 1 and then when it hits the 2nd Id it overwrites it with null note that you only have 1 Id in your array but two in the query. You will need to be a bit more selective in the query and alias some of the columns.

Select from 6 tables get one result only

I have about 6 tables and I am while looping on them the results comes 1 result it should be more
see my code here
$institute = $_POST['institute'];
$sections = $_POST['sections'];
$division = $_POST['division'];
$getSearch = $db->prepare("SELECT
a.name, a.phase, a.setNumber, a.email, a.sudImage, a.activity, a.id AS stud_id,
b.id, b.ins_name,
c.id, c.sec_name,
d.id, d.div_name,
e.id, e.std_id, e.sub_id, e.absence,
f.id, f.sub_name, f.subHour, f.level
FROM student_basic_info AS a
JOIN institutes AS b ON (a.institute = b.id)
CROSS JOIN ins_sections AS c ON (a.section = c.id)
CROSS JOIN ins_division AS d ON (a.division = d.id)
CROSS JOIN student_absence AS e ON (a.id = e.std_id)
CROSS JOIN ins_subjects AS f ON (e.sub_id = f.id)
WHERE a.institute =? AND a.section = ? AND a.division =?
GROUP BY a.id
");
$studSearch = array();
$getSearch->bind_param('iii', $institute, $sections, $division);
if ($getSearch->execute()) {
$results = $getSearch->get_result();
while ($vStud = mysqli_fetch_assoc($results)) {
$studSearch[] = $vStud;
var_dump($studSearch);
?>
the var_dump
array (size=1)
0 =>
array (size=17)
'name' => string 'الدفع النقدي' (length=23)
'phase' => string 'ابتدائي' (length=14)
'setNumber' => int 0
'email' => string 'johnef' (length=6)
'sudImage' => string '' (length=0)
'activity' => int 0
'stud_id' => int 7
'id' => int 3
'ins_name' => string 'معهد الفنون' (length=21)
'sec_name' => string 'فنون مسرح' (length=17)
'div_name' => string 'شعبة مرجانية 10' (length=26)
'std_id' => int 7
'sub_id' => int 3
'absence' => string '' (length=0)
'sub_name' => string 'فنون تطبيقية' (length=23)
'subHour' => string '2' (length=1)
'level' => string 'المستوي الأول' (length=25)
EDIT
SELECT a.name, a.phase, a.setNumber, a.email, a.sudImage, a.activity,
a.id AS stud_id, b.id, b.ins_name, c.id, c.sec_name, d.id, d.div_name,
e.id, e.std_id, e.sub_id, e.absence, f.id, f.sub_name, f.subHour, f.level
FROM student_basic_info AS a
JOIN institutes AS b ON (a.institute = b.id)
CROSS JOIN ins_sections AS c ON (a.section = c.id)
CROSS JOIN ins_division AS d ON (a.division = d.id)
CROSS JOIN student_absence AS e ON (a.id = e.std_id)
CROSS JOIN ins_subjects AS f ON (e.sub_id = f.id)
WHERE a.institute =1 AND a.section = 1 AND a.division =7
GROUP BY a.id
and yes I got the same results (1) record cam out which it should be at last (6) or (7) of records

Selecting the lastest record from a resultset (mysql, php) [duplicate]

This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 8 years ago.
I have written this code to get some info from my database.
"SELECT
c.from AS user_id,
c.time AS time,
u.user_firstname AS user_firstname,
u.user_lastname AS user_lastname,
u.user_profile_picture AS user_profile_picture
FROM chat c INNER JOIN users u ON u.user_id = c.from WHERE c.to = :id1
UNION SELECT
c.to AS user_id,
c.time AS time,
u2.user_firstname AS user_firstname,
u2.user_lastname AS user_lastname,
u2.user_profile_picture AS user_profile_picture
FROM chat c INNER JOIN users u2 ON u2.user_id = c.to WHERE c.from= :id2
ORDER BY time DESC"
it's work great except one thing. Since this is a inbox script there are many message from same user. but i only need to check if there is a message from this user or not.
array (size=28)
0 =>
array (size=5)
'user_id' => int 6
'time' => string '2014-05-13 19:53:58' (length=19)
'user_firstname' => string 'john' (length=4)
'user_lastname' => string 'doe' (length=3)
'user_profile_picture' => string '6_user_profile.jpg' (length=19)
1 =>
array (size=5)
'user_id' => int 2
'time' => string '2014-05-13 16:59:50' (length=19)
'user_firstname' => string 'james' (length=5)
'user_lastname' => string 'bond' (length=4)
'user_profile_picture' => string '2_user_profile.jpg' (length=19)
2 =>
array (size=5)
'user_id' => int 6
'time' => string '2014-05-13 02:15:44' (length=19)
'user_firstname' => string 'john' (length=4)
'user_lastname' => string 'doe' (length=3)
'user_profile_picture' => string '6_user_profile.jpg' (length=19)
3 =>
array (size=5)
'user_id' => int 6
'time' => string '2014-05-13 02:13:21' (length=19)
'user_firstname' => string 'john' (length=4)
'user_lastname' => string 'doe' (length=3)
'user_profile_picture' => string '6_user_profile.jpg'(length=19)
4 =>
array (size=5)
'user_id' => int 2
'time' => string '2014-05-13 01:58:59' (length=19)
'user_firstname' => string 'james' (length=5)
'user_lastname' => string 'bond' (length=4)
'user_profile_picture' => string '2_user_profile.jpg'(length=19)
as you can see in the var_dump there are 3 john doe and 2 james bond. but I need only the last ones according to the time.
so in this case john doe from 19:53:58, and james bond from 16:59:50. Like this:
array (size=2)
0 =>
array (size=5)
'user_id' => int 6
'time' => string '2014-05-13 19:53:58' (length=19)
'user_firstname' => string 'john' (length=4)
'user_lastname' => string 'doe' (length=3)
'user_profile_picture' => string '6_user_profile.jpg' (length=19)
1 =>
array (size=5)
'user_id' => int 2
'time' => string '2014-05-13 16:59:50' (length=19)
'user_firstname' => string 'james' (length=5)
'user_lastname' => string 'bond' (length=4)
'user_profile_picture' => string '2_user_profile.jpg' (length=19)
and if there are some other users i want to get their last records too.
how can i do this? is this possible with only one query?
try this one I tested.
"SELECT *
FROM (SELECT
c.from AS user_id,
c.time AS time,
u.user_firstname AS user_firstname,
u.user_lastname AS user_lastname,
u.user_profile_picture AS user_profile_picture
FROM chat c INNER JOIN users u ON u.user_id = c.from WHERE c.to = :id1
UNION
SELECT
c.to AS user_id,
c.time AS time,
u2.user_firstname AS user_firstname,
u2.user_lastname AS user_lastname,
u2.user_profile_picture AS user_profile_picture
FROM chat c INNER JOIN users u2 ON u2.user_id = c.to WHERE c.from= :id2
) AS bynames
GROUP BY user_id ORDER BY time ASC"
Put the union in a subquery, order it in the main query, and limit that to the most recent row.
SELECT *
FROM (SELECT
c.from AS user_id,
c.time AS time,
u.user_firstname AS user_firstname,
u.user_lastname AS user_lastname,
u.user_profile_picture AS user_profile_picture
FROM chat c INNER JOIN users u ON u.user_id = c.from WHERE c.to = :id1
UNION
SELECT
c.to AS user_id,
c.time AS time,
u2.user_firstname AS user_firstname,
u2.user_lastname AS user_lastname,
u2.user_profile_picture AS user_profile_picture
FROM chat c INNER JOIN users u2 ON u2.user_id = c.to WHERE c.from= :id2
)
ORDER BY time DESC
LIMIT 1
Untested
SELECT c.user_id
, MAX(c.time)
, u.user_firstname
, u.user_lastname
, u.user_profile_picture
FROM (
SELECT from AS user_id
, time
FROM chat
WHERE to = :id1
UNION
SELECT to AS user_id
, time
FROM chat
WHERE from = :id2
) as c
JOIN users u
ON u.user_id = c.user_id
GROUP BY c.user_id
, u.user_firstname
, u.user_lastname
, u.user_profile_picture

help getting products + their comments by followers with mysql

ok i have an product table. and a commment table. a user table and an social table.
social
SID AUID BUID
1 1 2 // user 1 follow 2
2 1 3 // user 1 follow 3
3 2 1
we can see that user id 1 is following user 2 and 3
user
UID NAME
1 me
2 imthenamefromuser2
3 imthenamefromuser3
product
PID UID NAME TIMECREATE
1 2 user2product 12-04-2011
2 3 user3product 12-03-2011
comment pcid = parent comment id
CID UID PID COMMENT PCID
1 1 2 comment on product2 NULL
2 2 2 another comment on p2 NULL
3 3 2 someoneelse on p2 NULL
4 1 2 who are you? 3
5 3 2 im user 3 dude 4
6 1 1 a new post on p2 NULL
ok the question is
how can we get the list of products their followers with their following comments ( max 20 comments ) ?
heres what i have so far ( without the comments ) lets example the $uid is 1
function listFromFollower($uid){
#here
$data = $this->fetchAll("SELECT products.name AS product, users.name, products.pid, products.timecreate
FROM products
INNER JOIN users ON users.uid = products.uid
INNER JOIN social ON products.uid = social.buid
WHERE social.auid = :uid", array( 'uid' => $uid));
return $data;
}
it gets something like
array
0 =>
array
'product' => string 'user2product' (length=9)
'name' => string 'imthenamefromuser2' (length=12)
'pid' => string '1' (length=1)
'timecreate' => string '2011-02-26 13:30:07' (length=19)
1 =>
array
'product' => string 'user3product' (length=8)
'name' => string 'imthenamefromuser3' (length=12)
'pid' => string '2' (length=1)
'timecreate' => string '2011-02-26 13:30:54' (length=19)
maybe it should be something like
array
0 =>
array
'product' => string 'user2product' (length=9)
'name' => string 'imthenamefromuser2' (length=12)
'pid' => string '1' (length=1)
'timecreate' => string '2011-02-26 13:30:07' (length=19)
0 =>
array
'name' => string ''
'comment' => string ''
1 =>
array
'name' => string ''
'comment' => string ''
0 =>
array
'name' => string 'a threaded comment'
'comment' => string ''
untill20 =>
array
'name' => string ''
'comment' => string ''
1 =>
array
'product' => string 'user3product' (length=8)
'name' => string 'imthenamefromuser3' (length=12)
'pid' => string '2' (length=1)
'timecreate' => string '2011-02-26 13:30:54' (length=19)
Thanks!
You can't get the result from the query to come out like you want. So there are two options. Run the query as you have and loop through each product to get their comments.
Or else get a large result that contains all the comments as well and them process to array to pull out the comments.
As Kevin Peno commented, is there any reason you need all this data? and not just the comment count? Because that would be a simple query with no processing.
Anyway here's a sample of how you could execute the 2nd option using a LEFT JOIN for comments:
function listFromFollower($uid){
$rows = $this->fetchAll("
SELECT products.name AS product, users.name, products.pid,
products.timecreate, commenters.name as commenter, comments.comment
FROM products
INNER JOIN users ON users.uid = products.uid
INNER JOIN social ON products.uid = social.buid
LEFT JOIN comments ON comments.pid = product.pid
INNER JOIN users AS commenters ON commenters.uid = comments.uid
WHERE social.auid = :uid", array( 'uid' => $uid));
$data = array();
foreach($rows as $row) {
// If we haven't added this product to data yet, add it.
if (!isset($data[$row['pid']])) {
$data[$row['pid']] = $row;
// Tidy up the data, we don't want commenter and comment here
unset($data[$row['pid']]['commenter']);
unset($data[$row['pid']]['comment']);
// Initialize an array for the comments
$data[$row['pid']]['comments'] = array();
}
$data[$row['pid']]['comments'][] = array(
'name' => $row['commenter'],
'comment' => $row['comment']
);
}
return $data;
}
Now you should have the same array as you had before, but now each element in the array with also have an array with the key comments that contains the comments.

Doctrine_Pager returns wrong results with multiple groupBy columns

I have Doctrine query setup with mySQL as database:
$q = Doctrine_Query::create();
$q->select('make.id, make.make,
model.id, model.year, model.model')
->from('Make make')
->innerJoin('make.Models model');
$q->groupBy('make.id, model.id'); // <-- this is where the problem
$q->orderBy('make ASC');
$q->setHydrationMode(Doctrine_Core::HYDRATE_SCALAR);
$pager = new Doctrine_Pager($q, 1, 1); // just want one result to prove the concept
$items = $pager->execute();
This executes this three queries (from mysql log):
SELECT COUNT(*) AS num_results FROM (SELECT m.id FROM make m INNER JOIN model m2 ON m.id = m2.make_id GROUP BY m.id, m2.id) dctrn_count_query
SELECT DISTINCT m3.id FROM make m3 INNER JOIN model m4 ON m3.id = m4.make_id GROUP BY m3.id, m4.id ORDER BY m3.make ASC LIMIT 1
SELECT m.id AS m__id, m.make AS m__make, m2.id AS m2__id, m2.year AS m2__year, m2.model AS m2__model FROM make m INNER JOIN model m2 ON m.id = m2.make_id WHERE m.id IN ('33') GROUP BY m.id, m2.id ORDER BY m.make ASC
And the result set is
array
0 =>
array
'make_id' => string '33' (length=2)
'make_make' => string 'Alfa-romeo' (length=10)
'model_id' => string '288' (length=3)
'model_year' => string '2010' (length=4)
'model_model' => string '159' (length=3)
1 =>
array
'make_id' => string '33' (length=2)
'make_make' => string 'Alfa-romeo' (length=10)
'model_id' => string '289' (length=3)
'model_year' => string '2010' (length=4)
'model_model' => string 'MiTo' (length=4)
2 =>
array
'make_id' => string '33' (length=2)
'make_make' => string 'Alfa-romeo' (length=10)
'model_id' => string '290' (length=3)
'model_year' => string '2010' (length=4)
'model_model' => string '159 SPORTWAGON' (length=14)
The problem is with second query that returns make.id which is used in third query to select 1 make (Alfa-Romeo which has 3 models). What I want is to return NUMBER OF make/model combinations.
If I change number of items returned in Doctrine_Pager to 2, I get 33 rows (because from two selected makes Alfa-Romeo has 3 models and Audi (which is next) has 30 models.
Where I'm making a mistake?
You can not combine multiple columns in a single group by. Try this...
$q->groupBy('make.id');
$q->addGroupBy('model.id');
or a little more compressed...
$q->groupBy('make.id')->addGroupBy('model.id');
$table->setAttribute(Doctrine_Core::ATTR_QUERY_LIMIT, Doctrine_Core::LIMIT_ROWS);
http://www.doctrine-project.org/projects/orm/1.2/docs/manual/dql-doctrine-query-language/en

Categories