Classic structure - self connected DB table, list - mysql

I have the following:
ID NAME PAREN_ID
1 a null
2 b null
3 c 2
4 d 3
I want to list the ID 4 item, and its all parent, so I would like to get:
4 d 3
3 c 2
2 b null
I tried something:
SELECT * FROM categories c1
JOIN categories c2 ON c2.ID = c1.PARENT_ID;
but thats not the good result, even if I try to filter to ID 4, it returns nothing.
Its MySQL!

I'm not really sure how you can do it with MySQL. I think your best bet would be fetching everything recursively.
function getCategories( $id ) {
$ret = array();
$cat = mysql_query( 'SELECT * FROM categories' );
$curid = $id;
do {
$ret[] = $cat[ $curid ];
$curid = $cat[ $curid ][ 'PARENT_ID' ];
} while ( $curid );
return $ret;
}
You should alter this so that it uses the PDO.
Only problem would be the query returning much data.

Related

Mysql Nested and declare as array

I have 2 table that want to call in and make another array from it.
The first table is groups
| id | name | type |
1 premium pr
2 basic bs
The second table is sub-groups
| id | group_id | name |
1 1 forever
2 2 short
Actually I want to show the code like this. To have another array function declare as sub-groups
Array (
[id] => 1
[name] => Premium
[type] => pr
)[sub-groups] => Array (
[0] => Array (
[id] => 1
[group_id] => 1
[name] => forever))
I created this PDO sql connection
=================EDITED CODE====================
function getGroups(){
global $conn;
$stmt = $conn->prepare("SELECT * FROM groups");
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$groups = $stmt->fetchAll();
foreach($groups as $key => $val){
$stmt = $conn->prepare("SELECT * FROM sub_groups WHERE group_id = {$val['id']}");
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$program = $stmt->fetchAll();
foreach($program as $key => $val){
$groups['sub-groups'] = $program;
}
}
return $groups;
}
The code successfully show the groups Premium and Basic, But it's not showing the sub-groups inside the main groups. Did I miss something?
Anyone with help will be nice.
Array keys have to be unique. If you have two columns with the same name, only one of them can appear in the resulting associative array for the rows.
You need to assign an alias to at least one of the columns with the same name so it will show up differently in the results.
SELECT g.name as group_name, sg.group_id, sg.id AS subgroup_id, sg.name AS subgroup_name
FROM groups AS g
LEFT JOIN subgroups AS sg ON sg.group_id = g.id
When you're creating the PHP result, $groups['sub-groups'] needs to be an array. You're overwriting it with a single element each time through the loop.
<?php
function getGroups(){
global $conn;
$groups = [];
$stmt = $conn->prepare("
SELECT g.name as group_name, sg.group_id, sg.id AS subgroup_id, sg.name AS subgroup_name
FROM groups AS g
LEFT JOIN subgroups AS sg ON sg.group_id = g.id");
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
while ($row = $stmt->fetch()){
if (!isset($groups[$row['group_name']])) {
$groups[$row['group_name']] = $row;
$groups[$row['group_name']]['sub-groups'] = [$row['subgroup_name']];
} else {
$groups[$row['group_name']]['sub-groups'][] = $row['subgroup_name'];
}
}
return $groups;
}

Add new columns into a existing TABLE using the values from a select query as the name of the new columns

I would like to use the values of a existing column in a table as the name of columns created into another existing table. At the same time insert the values achieved from another table into the new created columns.
I have the following:
Table: "feature_description" containing 4 columns.
feature_id feature_language feature_name feature_admin_name
2 2 Laktosefrei: Laktosefrei
....
there are 8 values under feature-admin_name. I would like to add 8 new columns into a existing Table "products" named after these 8 values.
Until now I have the following Code.
<?php
if ($conn = mysqli_connect("127.0.0.1", "root", "xxxxxxx", "fk16"))
{
$feature_index = "SELECT *
FROM feature_set_values AS fsv
LEFT JOIN feature_value_description AS fvd ON fsv.feature_value_id = fvd.feature_value_id
LEFT JOIN feature_value AS fv ON fv.feature_value_id = fvd.feature_value_id
LEFT JOIN feature_description AS fd ON fd.feature_id = fv.feature_id
LEFT JOIN feature_set_to_products AS fstp ON fstp.feature_set_id = fsv.feature_set_id";
if ($filter_query = mysqli_query($conn, $feature_index))
{
while ($filter_name = mysqli_fetch_array($filter_query))
{
//$feature_name = array();
$feature_name = $filter_name["feature_admin_name"];
//$feature_value = array();
$feature_value = $filter_name["feature_value_text"];
for ($i = 0; $i < count($filter_name['feature_admin_name']); $i++){
echo $filter_name['feature_admin_name'][$i]."\n<br />";
mysqli_query($conn, "ALTER TABLE products ADD (".$filter_name['feature_admin_name'][$i]." VARCHAR(50))");
}
}
//echo "</table>";
}
mysqli_close($conn);
}
else {
echo "My Fehler";
}
?>
But all I get are just 4 columns added into table "products" named with the Initials of the 8 values!
The 8 values are: Laktosefrei, Glutenfrei, Gentechnikfrei, BIO, Herkunft, Milchsorte, Labart, Milchbehandlung.
But I get 4 columns with the names: L, G, H, M.
What am I doing wrong? Kann please somebody help me in this matter.
Thankyou.
when "var_dump" used,
then I get the "echo" result:
Result of "var_dump" by "echo"
First of all, special thanks to Kishor, who gave me the right tip with var_dump().
I have now solved the problem as follows:
<?php
if ($conn = mysqli_connect("127.0.0.1", "root", "xxxxxx", "fk16"))
{
$feature_name = array();
$feature_index = "SELECT *
FROM feature_set_values AS fsv
LEFT JOIN feature_value_description AS fvd ON fsv.feature_value_id = fvd.feature_value_id
LEFT JOIN feature_value AS fv ON fv.feature_value_id = fvd.feature_value_id
LEFT JOIN feature_description AS fd ON fd.feature_id = fv.feature_id
LEFT JOIN feature_set_to_products AS fstp ON fstp.feature_set_id = fsv.feature_set_id
LEFT JOIN products AS p ON p.products_id = fstp.products_id";
if ($filter_query = mysqli_query($conn, $feature_index))
{
while ($filter_name = mysqli_fetch_array($filter_query))
{
$feature_name = array('id' => $filter_name["feature_id"], 'name' => $filter_name['feature_admin_name']);
foreach ($feature_name as $id => $name)
{
mysqli_query($conn, "ALTER TABLE products ADD (".$name." VARCHAR(20))");
}
}
mysqli_close($conn);
}
?>
Now, I get the 8 necessary values from the table feature_description.feature_admin_name
as the name of 8 new columns added into the table products as needed.
Once again thankyou for your help and tips in this matter.

How to simplify this 2 MySQL Queries

This must be an easy one, but I can't remember how I did it before.
I'm trying to make another query within the query where record IDs are match:
/*
tables:
models:
model_id
model_name
models_years:
model_year_id
model_id
year
*/
$models = DBW::run('SELECT * FROM models', [], true);
$models_years = DBW::run('SELECT * FROM models_years', [], true);
$output = [];
foreach ($models as $model)
{
$years = [];
foreach ($models_years as $model_year)
{
if ($model_year['model_id'] == $model['model_id'])
{
$years[] = $model_year['year'];
}
}
$output[] = [
'model_name' => $model['model_name'],
'years' => $years
];
}
var_dump( $output );
I use PDO (settings: ATTR_DEFAULT_FETCH_MODE = FETCH_ASSOC), and "DBW::run" function returns $stmt->fetchAll().
this is just an example of what I'm trying to do or improve, I know it's possible to do all of that in a single SQL, I've done it before and can't remember! :(
SELECT m.model_name, y.`year`
FROM models AS m
LEFT JOIN models_years As y ON m.model_id = y.model_id
OR from your original question, the following might be what you need:
SELECT m.model_name, group_concat(y.`year`) AS `year`
FROM models AS m
LEFT JOIN models_years As y ON m.model_id = y.model_id
GROUP BY 1
Why?
1 - Join table to reduce SQL calls
2 - GROUP the result (BY 1 == BY m.model_name, just a lazy shorthand here)
3 - group_concat(...) will by default produce: year1,year2,year3,... and then you can use PHP explode(',', ...) to change to array if you need
Join the tables, and use GROUP_CONCAT to combine all the years for each model. Then use explode() to split that into an array.
$output = DBW::run('select m.model_name, GROUP_CONCAT(y.year) AS years
FROM models AS m
LEFT JOIN models_years AS y ON m.model_id = y.model_id
GROUP BY m.model_id', [], true);
foreach ($output as &$row) {
$row['years'] = explode(',', $row['years']);
}
SELECT model_name, year FROM models, models_years WHERE
models.model_id=models_years.model_id
Or, if you prefer the JOIN syntax,
SELECT model_name, year FROM models JOIN models_years ON
models.model_id=models_years.model_id
another way to do this is with the sub select.
select * from models where model_id in (select model_id from models_years)

Loop through an array to unset a known value and implode to sql

I have two set of arrays in different MYSQL table. This what I want to do
What I Want TO Do
TABLE_ONE connect to the table.
get the value we want from session_id
THEN get the array associated with the value (session_id)
explode the array to get individual values.
NOW::::: - GO TO TABLE_TWO
TABLE_TWO Go straight to the first value from array (TABLE_ONE)
Explode the array associated with it.
Delete the number that's equal to the session_id
_____________________________________________________
And so fort....
More visual explanation below:
session_id = 4
TABLE_ONE:
id array1
1 4
2 1
3 2,5
4 1,3,4,5
5 4,5
TABLE_TWO:
id array2
1 4,6,9,2
2 3,7,8,2
3 7,12,4,9
4 1,5,4,8
5 3,6,12,3,5,4
So, because session_id = 4, we go to TABLE_ONE id 4. The array of id-4 is 1,3,4,5.
So now we know 4 can be found in id 1,3,4,5 of TABLE_TWO
We should now explode TABLE_TWO's array and delete 4 from there array. Implode the array and save the new value to database.
THIS IS WHAT I HAVE DONE - it would delete only '4' from them id-3 and delete all the values in id-4. Please help!!
$SESSION = 4;
$depSQL = mysql_query("SELECT array1 FROM TABLE_ONE WHERE id='$SESSION' LIMIT 1");
while($row=mysql_fetch_array($depSQL)) { $depARRAY = $row["array1"]; }
$explodedDEP = explode(",", $depARRAY);
foreach ($explodedDEP as $key1 => $value1) {
$stSQL = mysql_query("SELECT array2 FROM TABLE_TWO WHERE id='$value1'");
while($get=mysql_fetch_array($stSQL)) { $stARRAY = $get["array2"];}
$explodedST = explode(",", $stARRAY);
foreach ($explodedST as $key2 => $value2) {
if ($value2 == $SESSION) {
unset($explodedST[$key2]);
}
}
$newST = implode(",", $explodedST);
$sql = mysql_query("UPDATE TABLE_TWO SET array2 ='$newST' WHERE id='$value2'");
}
exit();
Please help!!! I'm really struggling on it.
I have tried it for hours now and i havent really got any where.
I think the problem is with the inserting to database.
Please help.
You can avoid one loop by using the array1 in your second SQL directly since it is already a comma seperated list.
Try this:
EDIT: Updated the code after testing.
$SESSION['ID'] = 4;
$depSQL = mysql_query("SELECT array1 FROM TABLE1 WHERE id='".$SESSION['ID']."' LIMIT 1");
while($row=mysql_fetch_array($depSQL))
{
$depARRAY = $row["array1"];
}
$stSQL = mysql_query("SELECT id, array2 FROM TABLE2 WHERE id IN ($depARRAY)") or die("Query Error");
while($get=mysql_fetch_array($stSQL)) {
$stARRAY = $get["array2"];
$id = $get["id"];
$explodedST = explode(",", $stARRAY);
foreach ($explodedST as $key2 => $value2) {
if ($value2 == $SESSION['ID']) {
unset($explodedST[$key2]);
}
}
$newST = implode(",", $explodedST);
echo $id . " " . $newST . "<BR/>" ;
$sql = mysql_query("UPDATE TABLE2 SET array2 ='$newST' WHERE id='$id'");
}
exit();
$SESSION is an array you can not assign value like this $SESSION = 4;
assign value like this
$SESSION['id'] = 4;
if ($value2 == $SESSION['id']) {

Sql (zend db select) of multiple selects

I need a bit of help.
I have (reference?) table with columns: id , user_id , key , value
It is pretty much a user profile table
and I would like to have SQL (I am using zend db table, but general SQL help will do) where I get "all 'user_id's where 'key' is somekey and 'value' is somevalue of that user_id but only if it also matches where 'key' is otherkey and 'value' is othervalue".
In other words I want to get users that have shoes of maker NIKE and color BLACK.
therefore 'key' is shoecolor and 'value' is BLACK and also another row with same user_id has 'key' is shoemaker and 'value' is NIKE.
This is what I could come up with, but doesn't work.
SELECT `user_profiles`.* FROM `user_profiles` WHERE
(`key` = 'shoecolor' AND `value` = 'BLACK') AND
(`key` = 'shoemaker' AND `value` = 'NIKE')
In case someone is knowledgable in zend db:
$where = array('shoecolor' => 'BLACK', 'shoemaker' => 'NIKE');
foreach ($where as $key => $value) {
$sql = $db->quoteInto('key = ?', $key);
$sql .= ' AND ' . $db->quoteInto('value = ?', $value);
$select->where($sql);
}
// make unique result
//$select->groupBy('user_id');
$resultSet = $zendTableInstance->fetchAll($select);
Please Help.
Thanx.
Because the key/value pair is in the row, your query is looking for a key that is 3 AND 4. No value can be 3 and 4 at the same time ;)
SELECT user_profiles.* FROM user_profiles WHERE (key = 3 AND value = 21) AND (key = 4 AND value = 55)
will not work.
You could do a join on yourself, and check for these values?
SELECT user_profiles.*
FROM user_profiles up1
JOIN user_profiles up2 ON up1.user_id = up2.user_id
WHERE
(up1.key = 3 AND up1.value = 21)
AND (up2.key = 4 AND up2.value = 55)