I've checked the queries in phpMyAdmin a lot of times and is dead sure they are absolutely correct. Also, if I manually write the loop 3 times, setting 2,3,4 instead of incrementing counter it still displays ONLY one column in last row. First two rows result is accurate.
foreach($row as $rec) is basically running 17 times from another query which is printing table headers.
$by_type1 = array("First","Second+","Final");
$counter = 2; //this counter represents type of interview (2-First, 3-Second+, 4-Final)
foreach ($by_type1 as $type1)
{
$table_row = '<tr><td class="rborder">'.$type1.'</td>';
foreach ($row as $rec)
{
$id=$rec['id'];
$qry2 = "SELECT
CONCAT( r.fname, ' ', r.lname ) AS rname,
ch.status_id as Type,
count(ch.status_id) as number
FROM candidateJoborderHistory ch
LEFT JOIN candidates_info c ON ch.candidate_id = c.candidate_id
LEFT JOIN recruiters r ON c.recruiter_id=r.recruiter_id
LEFT JOIN interviewtypes i ON ch.interview_id = i.interview_id
WHERE c.recruiter_id = $id AND UNIX_TIMESTAMP(ch.date_interview) BETWEEN 1401667200 AND
1402099200 AND ch.status_id = $counter
group by ch.status_id";
global $conn;
$conn->open();
$stmt2 = $conn->prepare($qry2);
$stmt2->execute();
$row2 = $stmt2->fetchAll();
foreach($row2 as $row_x)
{
$table_row .= '<td>'.$row_x['number'].'</td>';
}
}
$table_row .='</tr>';
echo $table_row . "\n";
$counter++;
}
What I want is:
First 6 6 4 4 11 6 12 3
Second+ 3 1 2 1 3
Final 3 2 1 4 1
But what I am getting is:
First 6 6 4 4 11 6 12 3
Second+ 3 1 2 1 3
Final 3
Well I think that is a MySQL approach, I've made some changes to your code and explained them:
$by_type1 = array(2=>"First", 3=>"Second+", 4=>"Final");
$counter = 2; //this counter represents type of interview (2-First, 3-Second+, 4-Final)
// Open connection first.
global $conn;
$conn->open();
// Using key => value array gets code simple
foreach ($by_type1 as $counter=>$type1)
{
$table_row = '<tr><td class="rborder">'.$type1.'</td>';
foreach ($row as $rec)
{
$id=$rec['id'];
$qry2 = "SELECT
CONCAT( r.fname, ' ', r.lname ) AS rname,
ch.status_id as Type,
count(ch.status_id) as number
FROM candidateJoborderHistory ch
LEFT JOIN candidates_info c ON ch.candidate_id = c.candidate_id
LEFT JOIN recruiters r ON c.recruiter_id=r.recruiter_id
LEFT JOIN interviewtypes i ON ch.interview_id = i.interview_id
WHERE c.recruiter_id = $id
AND UNIX_TIMESTAMP(ch.date_interview)
BETWEEN 1401667200 AND 1402099200
AND ch.status_id = $counter
GROUP BY ch.status_id";
$res = $conn->prepare($qry2);
$res->execute();
// Loop to get data...
while($row_x = $res->fetch(PDO::FETCH_ASSOC))
{
$table_row .= '<td>'.$row_x['number'].'</td>';
}
}
$table_row .='</tr>';
echo $table_row . "\n";
}
$conn->close();
Code isn't tested but if you have any doubt just ask. Hope it helps!
References:
Prepared Statements
Executing Statements
Related
I'm struggeling to get the corresponding values from table b using while loops. I have the following data in my database:
Table A
number - entity
3000 - ent1
3010 - ent1
4000 - ent1
Table B
number - entity
3000 - 10
3010 - 10
3010 - 20
4000 - 20
3000 - 30
4000 - 30
Now, I need the data to output the following table, where the first column is from table a and the next columns are populated from table b:
ent1 - 10 - 20 - 30
3000 - 3000 - null - 3000
3010 - 3010 - 3010 - null
4000 - null - 4000 - 4000
I have tried combining two WHILE loops, but with no success:
$query_entity = "SELECT number, entity FROM table_a ORDER BY number ASC";
$result_entity = mysqli_query($mysqli, $query_entity);
while ($entities = mysqli_fetch_array($result_entity)) {
$entitiesAccount = $entities['number'];
$query_entity_tabtwo = "SELECT number, entity
FROM table_b
WHERE number = $entitiesAccount";
$result_entity_tabtwo = mysqli_query($mysqli, $query_entity_tabtwo);
while ($entities_tabtwo = mysqli_fetch_array($result_entity_tabtwo)) {
echo $entitiesAccount . " - " . $entities_tabtwo['number'];
}
}
The result I'm getting is not the one I want stated above because the result does not separate the "entity" field in table b. How can I alter my script to get the desired result?
You simply need to echo things in a slighly different place
$sql = "SELECT number, entity
FROM table_a
ORDER BY number ASC";
$result = mysqli_query($mysqli, $sql);
while ($row = mysqli_fetch_array($result_entity)) {
$entitiesAccount = $row['number'];
$sql = "SELECT number, entity
FROM table_b
WHERE number = $entitiesAccount";
$result2 = mysqli_query($mysqli, $sql);
echo $entitiesAccount;
while ($row2 = mysqli_fetch_array($result2)) {
echo " - " . $row2['number'];
}
echo '<br>';
}
Cue: This is where JOINS join us in this endeavor. BA DUM TSSSS
You can use the ANSI syntax or the traditional where clause, they both work the same.
In your case, you could write something like..
SELECT ta.number, tb.entity
FROM tableA as ta
LEFT JOIN tableB as tb ON tb.number = ta.number
WHERE ta.entity = 'ent1'; // I suppose this is where you do the selection
Now you have all the rows from tableA and respectively related rows from tableB
and lets say that you have fetched all the result inside the array variable named.... umm.... $result.
Now, All you need is a little metaphorical sleight of hand in php as below...
<?php
$result = []; // This comes from the mysql
$output = [];
$columns_raw = [];
$entity_name = 'ent1'; // This comes from your selection logic the same that goes to sql.
foreach ($result as $row) {
$columns_raw[] = $row['entity'];
$output[$row['number']][$row['entity']][] = $row;
}
$columns = array_unique($columns_raw);
?>
let me write you a little html too.
<table>
<thead>
<th><?php echo $entity_name; ?></th>
<?php foreach ($columns as $column) { ?>
<th><?php echo $column; ?></th>
<?php } ?>
</thead>
<tbody>
<?php foreach ($output as $number => $row) { ?>
<tr><?php echo $number; ?></tr>
<tr><?php
foreach ($columns as $column) {
if (array_key_exists($column, $row)) {
echo $number;
} else {
echo 'null';
}
}
?></tr>
<?php } ?>
</tbody>
</table>
...and voila!
NOTE:- This is totally something which can be called a 'blind code' and I didn't run it. But this should be enough to point you in the right direction.
You can generate the data entirely in one query. This way you can simplify your PHP to one while loop:
SELECT a.number AS ent1,
GROUP_CONCAT(CASE WHEN b.entity = 10 THEN b.number END) AS `10`,
GROUP_CONCAT(CASE WHEN b.entity = 20 THEN b.number END) AS `20`,
GROUP_CONCAT(CASE WHEN b.entity = 30 THEN b.number END) AS `30`
FROM table_a a
JOIN table_b b ON b.number = a.number
GROUP BY ent1
Output:
ent1 10 20 30
3000 3000 (null) 3000
3010 3010 3010 (null)
4000 (null) 4000 4000
Demo
I am stuck for 12 hours now. My problem is to build query for filtering based on XY number of parameters.
Background:
Item:
An item(s) can have many attributes, each attribute is related to only one item.
Attribute[id, type_id, value_id, item_id]:
type (relation to AttributeType[id, name]) ex.: operating.system (column "name" of AttributeType)
value (relation to AttributeValue[id, value]) ex.: Windows Phone 8 (column "value" of AttributeValue)
Scenario:
At the page, where I list items, there is filter for attributes
Operating System
{checkbox name="a[type.id][0]" value="[value.id]"} Windows Phone 8
{checkbox name="a[type.id][1]" value="[value.id]"} Android
Cpu Frequncy
{select with options name="a[type.id][0]"}{option value="a[type.id][value.id]" }{/select}
When user submits the search form, I loop throug attributes and I dynamically add andWhere(). And query looks like:
select .... from items i left join attributes a on i.id = a.item_id WHERE
a.type_id=typeid and a.value_id=valueid
When i do this with only 1 param its ok but with 2 params
a.type_id=typeid AND a.value_id=valueid AND a.type_id=typeid AND a.value_id=valueid.....
result is 0
a.type_id=typeid AND a.value_id=valueid OR a.type_id=typeid AND a.value_id=valueid....
returns every item where least 1 param matched
What I need, is to build query that results items that have all parameters matching. Like a subquery loop, match first search attribute than from that result match second, third,... and finally get result of items.
Thank you
----- EDIT ------
I have proceed, i am creating subqueries like
$sAttrTypes = (isset($_GET["a"]) ? $_GET["a"] : array());
$qb = $this->em()->createQueryBuilder("p");
$qb->select(array("i", "a"))->from("ErikOfferBundle:Item", "i")->leftJoin("i.attributes", "a");
$i = 0;
$subquery_0 = false;
foreach ($sAttrTypes as $aTypeId => $aValues) {
if (!$aValues) {
continue;
}
$ids = false;
foreach ($aValues as $value) {
$ids[] = $value[0];
}
$query = $this->em()->createQueryBuilder("p_" . $i);
${"subquery_" . $i} = $query->select(array("i$i", "a$i"))
->from("ErikOfferBundle:Item", "i$i")
->leftJoin("i$i.attributes", "a$i");
if (count($ids) < 2) {
${"subquery_" . $i}->where($qb->expr()->eq("a$i.value", $ids[0]));
} else {
${"subquery_" . $i}->where($qb->expr()->in("a$i.value", $ids));
}
if ($i > 0) {
${"subquery_" . ($i - 1)}->andWhere($qb->expr()->in("i" . ($i - 1) . ".id", ${"subquery_" . $i}->getDql()));
}
echo "subquery_" . $i. ": " .${"subquery_" . $i}."<br/>";
$i++;
}
$qb->where($qb->expr()->in("i.id", ${"subquery_0"}->getDql()));
echo "Final query: " . $qb->getDql();
$items = $qb->getQuery()->getResult();
that creates query:
subquery_0: SELECT i0, a0 FROM ErikOfferBundle:Item i0 LEFT JOIN i0.attributes a0 WHERE a0.value = 1
subquery_1: SELECT i1, a1 FROM ErikOfferBundle:Item i1 LEFT JOIN i1.attributes a1 WHERE a1.value = 4
Final query: SELECT i, a FROM ErikOfferBundle:Item i LEFT JOIN i.attributes a WHERE i.id IN(SELECT i0, a0 FROM ErikOfferBundle:Item i0 LEFT JOIN i0.attributes a0 WHERE a0.value = 1 AND i0.id IN(SELECT i1, a1 FROM ErikOfferBundle:Item i1 LEFT JOIN i1.attributes a1 WHERE a1.value = 4))
And it gets exception "[Syntax Error] line 0, col 88: Error: Expected Doctrine\ORM\Query\Lexer::T_FROM, got ','"
col 88 is "i0, a0" in first subquery
Solved with selecting only 1 table in subqueries
final draft code:
$sAttrTypes = (isset($_GET["a"]) ? $_GET["a"] : array());
$i = 0;
$subquery_0 = false;
foreach ($sAttrTypes as $aValues) {
if (!$aValues[1]) {
continue;
}
if (count($aValues) == 1 && ($aValues[1] == 0 || $aValues[1] == "")) {
continue;
}
$query = $this->em()->createQueryBuilder();
${"subquery_" . $i} = $query->select(array("i$i"))
->from("ErikOfferBundle:Item", "i$i")
->leftJoin("i$i.attributes", "a$i")
->where((count($aValues) == 1 ?
$query->expr()->eq("a$i.value", $aValues[1]) :
$query->expr()->in("a$i.value", $aValues)));
if ($i > 0) {
${"subquery_" . (0)}->andWhere($query->expr()->in("i0.id", ${"subquery_" . $i}->getDQL()));
}
$i++;
}
$qb = $this->em()->createQueryBuilder();
$qb->select(array("i", "a"))->from("ErikOfferBundle:Item", "i")->leftJoin("i.attributes", "a");
if ($subquery_0) {
$qb->andWhere($qb->expr()->in("i.id", $subquery_0->getDQL()));
}
$items = $qb->getQuery()->getResult();
I have this php code - for loop and on every step , every increment search for data in mysql table aktivnosti
PHP:
for ($i=1; $i<=30; $i++;){
$temp = array();
$temp['ID'] = $i;
// ATTEMP TO GET DATA FROM aktivnosti WHERE id_activity = $i
$rs1 = $db->prepare('SELECT naziv FROM aktivnosti WHERE id_activity=:idd');
$rs1->bindParam(':idd', $i);
$rs1->execute();
$naz = $rs1->fetchColumn();
$temp['activity'] = '<button>'.$naz.'</button>';
$output['data'][] = $temp;
}
$jsonTable = json_encode($output);
So as you can see from code above I try to get data on every $i increment and search if id_activity on table aktivnosti = $i
I get just one result so I get just first 'naziv', I need to get all naziv data from table aktivnosti where id_activity = $i and create:
<button>$naz[0]<button>
<button>$naz[1]<button>
<button>$naz[2]<button>
<button>$naz[how many times id_activity = $i]<button>
How I can do that? Some ideas?
sorry for my engish. Thanks
As pointed out in comments above, you are taking a bad approach here. You should be able to get all this data in a single query. You probably also need to take a look at your schema if you want to have the concept of a fixed number of 30 days with each days related to n number of records. I would suggest two tables
day_list
day_id day_name (or any other day-related data fields)
1 ...
2 ...
... ...
30 ...
days_records
record_id day_id other_data
1 1 ...
2 1 ...
3 3 ...
4 5 ...
...
You would then query this like:
SELECT
d.day_id AS day_id
dr.record_id AS record_id
dr.other_date AS other_data
FROM day_list AS d
LEFT JOIN day_records AS dr
ON d.day_id = dr.day_id
Sorry for the change in table names, as don't know what your database schema represents in real-world terms.
You then make a single query like:
$query = <<<EOT
SELECT
d.day_id AS day_id
dr.record_id AS record_id
dr.other_date AS other_data
FROM day_list AS d
LEFT JOIN day_records AS dr
ON d.day_id = dr.day_id
EOT;
$rs1 = $db->execute($query);
if (false === $rs1) {
// something went wrong. perhaps log an error
} else {
while($row = $rs1->fetch(PDO::FETCH_ASSOC)) {
$temp = $row;
// check to see if this date has a record
if (empty($temp['record_id'])) {
// this is a day with no associated record.
// do something
}
// not shown - continue to manipulate your $temp as desired
// then add to output array
$output['data'][] = $temp
}
}
If you need both ID and activity:
$sql = <<<EOD
SELECT
id_activity AS ID,
CONCAT('<button>', naziv, '</button>') AS activity
FROM aktivnosti
WHERE id_activity BETWEEN 1 AND 30
ORDER BY id_activity
EOD;
$data = $db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
$jsonTable = json_encode(compact('data'));
If you only use activity:
$sql = <<<EOD
SELECT CONCAT('<button>', naziv, '</button>')
FROM aktivnosti
WHERE id_activity BETWEEN 1 AND 30
ORDER BY id_activity
EOD;
$data = $db->query($sql)->fetchAll(PDO::FETCH_COLUMN, 0);
$jsonTable = json_encode(compact('data'));
try this...
while($naz=$rs1->fetch(PDO::FETCH_OBJ))
{
echo $naz->column1;
echo $naz->column2;
}
instead of
$naz = $rs1->fetchColumn();
I want to get Name and corresponding Score at the latest time. So I tried:
$queryObj = mysql_query("SELECT `Name`,`Score` from `Table`.`Score` where `Date` = ( SELECT max(`Date`) from `Table`.`Score`) and `Name`<>'' ");
then get value from it by:
while( $obj = mysql_fetch_object( $queryObj ) ) {
$data = array();
$data['Name'] = $obj->Name;
$data['Score'] = $obj->Score;
$searches[] = $data;
}
But when I print :
print_r(array_values($searches));
the first value is missing in the array, so that won't be the right way.
I also tried:
$row = mysql_fetch_assoc($queryObj);
for ($i = 0; $i <3; $i++)
print( $row['Name'][$i]." Score: ".$row['Score'][$i]."<br />\n");
But it won't give me the right results also. How do I get the value from that query? (the query is correct, I tested it). Any body has suggestion ?
Edit: I add my sample data here:
Name Score Date
abc 3 2013-08-29 10:11:47
abc 2 2013-08-29 09:39:23
abc 1 2013-08-28 10:22:28
jane 2 2013-08-29 09:39:23
2013-08-29 10:08:36
jane 1 2013-08-29 10:11:47
tarzan 1 2013-08-29 10:11:47
Note: Yes, there is some blank values.
My expected result would be:
abc score 3
jane score 1
tarzan score 1
Ok, so after you have updated your question and provided what you expect, your query should look like this:
SELECT t1.Name, t1.Score
FROM Table.Score t1
INNER JOIN
(
SELECT max(Date) MaxDate, Name, Score
FROM Table.Score
WHERE Name <> ''
GROUP BY Name
) t2
ON t1.Name = t2.Name AND t1.Date = t2.MaxDate
This will give you pairs of Name and Score for each Name with Score based on his latest Date (1 row per Name).
So replace your original query with mine in this line:
$queryObj = mysql_query(" ... ");
Then:
$rows = array();
while($row = mysql_fetch_assoc($queryObj)) {
$rows[$row['Name']] = $row['Score'];
}
And you can nicely foreach it in the exact way you wanted in your last comment:
foreach($rows as $name => $score) {
echo $name . ' - ' . $score . "\n";
}
I have a table containing (essentially) three columns - id, name, ref_id.
I would like to create an indented list where the columns with ref_id would be indented below the column with the corresponding id, for example:
Name | ID | Ref ID
about 1 0
story 2 1
history 3 1
contact 4 0
help 5 0
map 6 4
directions 7 4
Would ideally create something like this:
about
- story
- history
contact
- map
- directions
help
What would be ideal is one MySQL query that would return the full list as above, if not something that would create it with the least amount of SQL calls and cpu usage. The only way I can think of doing it is incredibly wasteful and I am sure there is a better way.
Thanks in advance!
--MySQL 5.1 happiness
SELECT
CASE WHEN tp.Level = 1 THEN tp.Parent
ELSE CONCAT( '- ', tp.Name)
END AS result
FROM (
SELECT
t.name,
CASE
WHEN t.ref_id = 0 THEN t.name
ELSE t2.name
END AS Parent,
CASE
WHEN t.ref_id = 0 THEN 1
ELSE 2
END AS Level
FROM question_1900097 t
LEFT JOIN question_1900097 t2 ON t.ref_id = t2.id
) AS tp
ORDER BY tp.Parent, tp.Name;
The PHP version
$in = array(
array('about',1,0),
array('story',2,1),
array('history',3,1),
array('contact',4,0),
array('help',5,0),
array('map',6,4),
array('directions',7,4)
);
foreach ($in as $k => $v) {
if ($v[2] === 0) { $out[$v[1]][0] = $v; };
if ($v[2] > 0) { $out[$v[2]][1][] = $v;};
}
foreach ($out as $k => $v) {
echo $v[0][0] . "\n";
if (isset($v[1])) {
foreach ($v[1] as $sk => $sv) {
echo " - " .$sv[0] . "\n";
}
}
}