I am building some sort of a CMS in PHP and i ran into an issue, hoping you guys can help me out with it.
I'll post an example of what my database looks like and what i need to be done.
ID | Name | Order
1 | A1 | 1
2 | A2 | 3
3 | A3 | 4
4 | A4 | 2
What i need is a way to edit the 'order' column of DB dynamically, as in if i was to change the order of 'A2' to '2', it will automatically change the order of 'A4' which was originally '2' and update it to whatever order 'A2' was, which is '3'
If this wasn't clear enough, i would be more than happy to screen shot my database to clarify it more.
Thanks in advance
change the order of 'A2' to '2', it will automatically change the
order of 'A4' which was originally '2' and update it to whatever order
'A2' was, which is '3'
UPDATE Orders SET `Order` = (SELECT `Order` FROM Orders WHERE id = 2) WHERE `Order` = 4;
UPDATE Orders SET `Order` = 3 WHERE id = 2;
Related
I have a nested array like the following:-
array(
array(
'id' => 45cfeteuid536hjj929,
'name' = 'Cuisines',
'children' => array(
array(
'id' => 45gcfeteuid536hjj929,
'name' = 'Itlaian',
),
array(
'id' => 45bjfe78ng5d536hjj92,
'name' = 'Indian',
'children' => array(
array(
'id' => 457hfe78ng5d53ghy56j,
'name' = 'Punjabi'
)
)
)
)
)
);
I have a table like this:-
|--------------------------------|
| id | name | parent_id |
|--------------------------------|
I want data to be inserted like this:-
|---------------------------------------------------------------|
| id | name | parent_id | api_id |
|---------------------------------------------------------------|
| 1 | Cuisines | 0 | 45cfeteuid536hjj929 |
|---------------------------------------------------------------|
| 2 | Italian | 1 | 45gcfeteuid536hjj929 |
|---------------------------------------------------------------|
| 3 | Indian | 1 | 45bjfe78ng5d536hjj92 |
|---------------------------------------------------------------|
| 4 | Punjabi | 3 | 457hfe78ng5d53ghy56j |
|---------------------------------------------------------------|
The parent_id of the child is the id of the object to which it belongs. The id of the table are autoincrement value generated automatically by the mysql db.
For example:-
Step 1: While saving Cuisine, the id (autoincrement in nature) saved
is 1. Since it is the root, hence parent_id = 0.
Step 2: While saving Italian, the id (autoincrement in nature)
saved is 1. Since it is a child of Cuisines, the parent_id = 1
How can I save the nested array in such way?
One way would be to generate insert statements that look like this (assuming your table is called tab):
insert into tab(name, parent_id, app_id)
select 'Cuisines', coalesce(min(id), 0), '45cfeteuid536hjj929' from tab
where app_id = '';
insert into tab(name, parent_id, app_id)
select 'Itlaian', coalesce(min(id), 0), '45gcfeteuid536hjj929' from tab
where app_id = '45cfeteuid536hjj929';
insert into tab(name, parent_id, app_id)
select 'Indian', coalesce(min(id), 0), '45bjfe78ng5d536hjj92' from tab
where app_id = '45cfeteuid536hjj929';
insert into tab(name, parent_id, app_id)
select 'Punjabi', coalesce(min(id), 0), '457hfe78ng5d53ghy56j' from tab
where app_id = '45bjfe78ng5d536hjj92';
These queries will find the parent ID via the app_id that parent should have. No value for the id column is inserted, as it is assumed that the database will generate it upon insertion.
Here is a recursive PHP function which generates those statements. You'll have to adapt it to actually execute those statements with whatever API you use (PDO, mysqli, ...):
function insertRecords($data, $parent = "") {
foreach($data as $row) {
// Replace next echo statement with the code to actually execute this SQL:
echo "insert into tab(name, parent_id, app_id) select '$row[name]', coalesce(min(id), 0), '$row[id]' from tab where app_id = '$parent';\n";
if (isset($row["children"])) insertRecords($row["children"], $row["id"]);
}
}
Assuming your nested data structure is stored in variable $data, call the above function like this:
insertRecords($data);
Hi i have a table name messages i want to get last message from chat conversation between two users.
Table -
id from_id to_id text created
========================================
1 1 2 hi 2014-12-01 10:30:10
2 2 1 Hello 2014-12-01 10:30:20
3 3 1 Hi chinu 2014-12-01 10:32:02
4 3 1 hw r u? 2014-12-01 10:32:22
5 2 1 h r u? 2014-12-01 10:33:01
Please check my query =
//$user_id=$this->Session->read('Auth.User.id');
$user_id=1;
$fields=array('DISTINCT(Message.from_id), Message.id, Message.text, Message.created');
$this->Paginator->settings = array(
'conditions'=>array('Message.to_id'=>$user_id),
'limit' => 30,
'order' => array(
'Message.created' => 'DESC',
'Message.id' => 'DESC'
),
'fields'=>$fields,
'group'=>array('Message.from_id')
);
$inbox = $this->Paginator->paginate('Message');
pr($inbox);
$this->set('inbox', $inbox);
I want to get last message conversation between 2 and 3 id. The output looks like -
id from_id to_id text created
========================================
5 2 1 h r u? 2014-12-01 10:33:01
4 3 1 hw r u? 2014-12-01 10:32:22
Please help me. If you don't know the cakephp please post core php MySQL query here.
Thanks
chatfun
Please check this query -
SELECT * FROM (SELECT DISTINCT * FROM messages WHERE (from_id=1 OR to_id=1) ORDER BY created DESC) as m GROUP BY `from_id`
I suppose this query would work (although I don't understand why 'to_id' = 1 in your expected output, maybe I didn't get your purpose right)
SELECT 'id', 'from_id', 'to_id', 'text', 'created'
FROM Message
WHERE ('from_id' = 2 AND 'to_id' = 3) OR ('from_id' = 3 AND 'to_id' = 2)
ORDER BY created DESC
LIMIT 1
This how the query looks like to achieve what you are looking at , i.e. getting the last conversation from each from_id
select t1.* from Message
t1 left join Message t2
on t1.from_id = t2.from_id
and t1.id<t2.id where t2.id is null;
You have a primary key id auto_incremented so it could be used in the comparison instead of date.
Or
select t1.* from Message t1
where not exists (
select 1 from Message t2 where t1.from_id = t2.from_id and t1.id < t2.id
);
alright best way for me to explain is by giving an example
Table 1
ID | name | class
-------------------------
1 | first name | a
2 | second name | b
Table 2
ID | name_id | meta_key | meta_value |
-------------------------------------------------------
1 | 1 | image | someImage.jpg |
2 | 1 | description | very long description |
3 | 2 | image | someImage_2.jpg |
4 | 2 | description | very long description 2 |
I am trying to select name and class from Table 1, and also all the records from Table 2 that has the same name_id as ID (in Table 1).
Here is the query i have now:
SELECT
table1.name,
table1.class,
table2.name_id,
table2.meta_key,
table2.meta_value
FROM
table1
LEFT JOIN
table2 ON ( table1.ID = table2.name_id )
WHERE
table1.ID = '2'
This works and return an array with as many elements as the Table 2 entries that has name_id = 2
Is there a way to return an array with 1 the result from first table, and another array with results from the second table ?
Update:
The ideal results will be:
$result['table1'][0] = array('name' => 'second name',
'class' => 'b')
$result['table2'][0] = array('name_id' => 2,
'meta_key' => 'image',
'meta_value' => 'someImage_2.jpg')
$result['table2'][1] = array('name_id' => 2,
'meta_key' => 'description',
'meta_value' => 'very long description 2')
hopes that makes sense.
I'd split the result array AFTER fetching it from the database...
//Assuming your result-set is assigned to $result:
$table1_keys = array('id', 'name', 'class');
$table2_keys = array('id', 'name_id', 'meta_key', 'meta_value');
$table1_results = array();
$table2_results = array();
foreach($result as $key => $val) {
if(in_array($key, $table1_keys)) {
$table1_results[] = $val;
}
if(in_array($key, $table2_keys)) {
$table2_results[] = $val;
}
}
After this, your result-set should be split into two arrays: $table1_results and $table2_results.
Hope this helps you.
I don't believe there's a way to do it in SQL but I'd label each table so it can be done generically in PHP.
SELECT
':table1',
table1.name,
table1.class,
':table2',
table2.name_id,
table2.meta_key,
table2.meta_value
FROM ...
Although personally I'd just do this.
SELECT 'table1', table1.*, ':table2', table2.*
FROM ...
That makes it easier to duplicate entire rows between client and server and reduces maintenance when you decide to add a new field.
However in your query you are duplicating table1 for each row returned so perhaps this would be better.
SELECT
table1.*,
table2a.meta_value AS image,
table2b.meta_value AS description
FROM
table1
LEFT JOIN
table2 AS table2a ON ( table1.ID = table2a.name_id AND table2a.meta_key = 'image' )
LEFT JOIN
table2 AS table2b ON ( table1.ID = table2b.name_id AND table2b.meta_key = 'description' )
WHERE
table1.ID = '2'
I want to count to an extra field created, the matches from a join. Is this possible in CakePHP?
I have an example of my data that I curently have.
And how would a query look in mySQL for this type of result?
Table:goal
id | name
-----------
1 Goal X
2 Goal Y
Table: tasks
id | name | goal_id
-------------------
1 task1 1
2 task2 1
3 task3 2
4 task4 2
5 task5 2
Result
id | name | matches
-------------------
1 goal1 2
2 goal2 3
MySQL query :
SELECT goal.id, goal.name, Count( * ) AS matches
FROM goal
RIGHT JOIN task ON goal.id = task.goal_id
GROUP BY goal.id
CakePHP : [if you have model with name Goal and Task]
$options['fields'] = array(
'Goal.id',
'Goal.name',
'count(*) AS matches'
);
$options['joins'] = array(
array(
'table' => 'tasks',
'alias' => 'Task',
'type' => 'Right',
'conditions' => array(
'Goal.id = Task.goal_id'
)
)
);
$options['group'] = array('Goal.id');
$result = $this->Goal->find('all', $options);
mysql should be that:
Select goal.id,goal.name,Count(*) From goal RIGHT JOIN tasks on goal.id=tasks.goal_id Group by goal.id
CakePHP, can't tell you without testing...
I would like to use data from an array to add a column and make a join on a MySql table.
Let's say, on one hand, we have an array ($relevance):
$relevance = array(
array('product_id' => 1, 'relevance' => 2),
array('product_id' => 2, 'relevance' => 5),
array('product_id' => 3, 'relevance' => 1),
);
And on the other hand, we have this table (products):
product_id | product_name
--------------------------
1 | Product 1
2 | Product 2
3 | Product 3
Now, I want to select data from the products table and joining them with $relevance based on their product_id in order to get something like this:
product_id | product_name | relevance
---------------------------------------
1 | Product 1 | 2
2 | Product 2 | 5
3 | Product 3 | 1
In other words, how can I make a SELECT with LEFT JOIN using data from both the MySql database and an array which would "mean" something like this:
SELECT `p`.*, `{{$relevance}}`.* FROM `products` AS `p`
LEFT JOIN `{{$relevance}}`
ON p.product_id = {{$relevance}}.product_id
pure sql solution, not efficient though for big recordsets:
$relevances = array()
foreach ($relevance as $v){
$relevances[] = "SELECT {$v['product_id']} as product_id, {$v['relevance']} as relevance"
}
$sql = implode(' UNION ', $relevances);
$sql = "SELECT p.product_id, p.product_name, r.relevance
FROM products p
JOIN ($sql) r ON p.product_id=r.product_id";
Well, you can make another table relevance and then you could just use JOIN. Or you can use loop to get those data. Something like
$relevance = array(
array(1, 'relevance' => 2),
array(2, 'relevance' => 5),
array(3, 'relevance' => 1),
);
$q = mysql_query("SELECT * FROM products")
while($r = mysql_fetch_assoc($q))
{
$productRelevance = $relevance[$r['prod_id']-1];
}
Hoewever this code may fail if you delete some product and those ids wouldn' be in order, e.g.: 1,2,5,6,7,10. I recommend you to use another table.