Deutsch

Делаю тестовое задание

285  1 2 все
miltorg коренной житель25.09.14 19:46
miltorg
NEW 25.09.14 19:46 
Задание PHP+MySQL[править]
Табличка с данными. Там всего несколько полей и несколько строк. По parent_id есть привязка к id, т.е. родитель - последователь. У каждой строчки есть значение value. Вот хотелось бы на выходе получить табличку вида
Name (имя в поле name) -
value (сумма текущего значения + сумма всех последователей по parent_id)
Важно! Используйте PHP5.5 - mysqli вместо устаревшего mysql
Таблица:
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=*/;

/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*Table structure for table `table1` */
DROP TABLE IF EXISTS `table1`;
CREATE TABLE `table1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT '0',
`name` varchar(255) DEFAULT NULL,
`value` int(11) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;

/*Data for the table `table1` */
insert into `table1`(`id`,`parent_id`,`name`,`value`) values (1,0,'test1',0),(2,0,'test2',30),(3,1,'test3',31),(4,6,'test4',77),(5,3,'test5',45),(6,2,'test6',20),(7,5,'test7',10);
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
Результат[править]
Должно получиться нечто такое:
id parent_id name value sum
1 0 test1 0 86
2 0 test2 30 127
3 1 test3 31 86
4 6 test4 77 77
5 3 test5 45 55
6 2 test6 20 97
7 5 test7 10 10
Половина евро в час
#1 
NightWatch коренной житель25.09.14 21:21
NightWatch
NEW 25.09.14 21:21 
в ответ miltorg 25.09.14 19:46
А в чем проблема?
#2 
miltorg коренной житель25.09.14 21:23
miltorg
NEW 25.09.14 21:23 
в ответ NightWatch 25.09.14 21:21
Сделать.
Если это правда тестовое задание - времени оно должно занять мало.
Половина евро в час
#3 
miltorg коренной житель25.09.14 21:55
miltorg
NEW 25.09.14 21:55 
в ответ miltorg 25.09.14 21:23
Простой алгоритм не нашёл.
Половина евро в час
#4 
  Posmotrim знакомое лицо25.09.14 22:20
Posmotrim
NEW 25.09.14 22:20 
в ответ miltorg 25.09.14 21:55
так его не искать, нужно, а реализовать :)
вот держи, с минимальной оптимизацией. допилишь, если нужно:
public function actionTest()
{
//вот тут сделаешь чтение посредством mysqli, как тебе нужно в задании
//я для теста посредством yii загнал все записи в массив ассоциативных массивов
$cmd = Yii::app()->db->createCommand("select * from table1");
$items = $cmd->queryAll(true);

$helper = new SumCalculator($items);

foreach($items as $item)
{
echo "{$item['id']}\t{$item['parent_id']}\t{$item['name']}\t{$item['value']}\t";
echo $helper->calc($item['id']) . "
\n";
}
}


ну и сам расчёт с минимальной оптимизацией

class SumCalculator
{
private $sums = [];
private $key2val = [];//словарь (ключ => значение)
private $children = []; //словарь (ключ => [child1, child2, ...])
function SumCalculator($items)
{
foreach($items as $item)
{
$this->key2val[$item['id']] = $item['value'];
if($item['parent_id'] != 0)
{
$this->children[$item['parent_id']][] = $item['id'];
}
}
}

public function calc($id)
{
if(!isset($this->sums[$id]))
{
$sum = $this->key2val[$id];
if(isset($this->children[$id]))
{
foreach($this->children[$id] as $child_id)
{
$sum += $this->calc($child_id);
}
}
$this->sums[$id] = $sum;
}
return $this->sums[$id];
}
}


#5 
miltorg коренной житель26.09.14 01:16
miltorg
NEW 26.09.14 01:16 
в ответ miltorg 25.09.14 21:55, Последний раз изменено 26.09.14 01:17 (miltorg)
Сам придумал:
$res = $mysqli->query("SELECT * FROM `table1`");
while ($row = $res->fetch_assoc()) {
$sum[$row['id']][1] = $row['value'];
$otvet[$row['id']]= $row['value'];
}
$plus=1;
while ($i++<10){
if ($plus==1){
$plus=0;
$res->data_seek(0);
while ($row = $res->fetch_assoc()) {
if ($row['parent_id'] == 0) continue;
if ($sum[$row['id']][$i]){
$sum[$row['parent_id']][$i+1]=$sum[$row['id']][$i];
$otvet[$row['parent_id']]= $otvet[$row['parent_id']]+$sum[$row['id']][$i];
$plus=1;
}
}
}
}
Рабочий пример:
http://fx-signal.ru/u.php
Половина евро в час
#6 
  Posmotrim знакомое лицо26.09.14 12:06
Posmotrim
NEW 26.09.14 12:06 
в ответ miltorg 26.09.14 01:16, Последний раз изменено 26.09.14 12:33 (Posmotrim)
В ответ на:
Сам придумал:

1) Избегай магических чисел(я про 10)
2) Алгоритм расчёта неверен. Можешь убедиться на следующих тестовых данных:

INSERT INTO `table1` VALUES (1,0,'test1',0),(2,0,'test2',30),(3,1,'test3',31),(4,6,'test4',77),(5,3,'test5',45),(6,2,'test6',20),(7,6,'test7',10);


Добавил:
3) Форматируй код. Иначе его даже смотреть никто не будет. Это чистое неуважение, как к возможному работодателю(простительно), так и читателям форума(расстрельная статья :) ).
4) Даже в тестовом задании, комментарии никто не отменял.

#7 
Murr патриот26.09.14 12:40
Murr
NEW 26.09.14 12:40 
в ответ Posmotrim 26.09.14 12:06
Это чистое неуважение
------
Это точно - у меня на вертилкальном экране даже кнопика "ответить" от длинного <INSERT> не видно...
#8 
Murr патриот26.09.14 12:41
Murr
NEW 26.09.14 12:41 
в ответ miltorg 25.09.14 19:46
Подсказка - <Oracle> работает с деревьями изначально...
#9 
miltorg коренной житель26.09.14 12:44
miltorg
NEW 26.09.14 12:44 
в ответ Posmotrim 26.09.14 12:06
Тут один родитель у двух - В задании такого нет.
Сейчас гляну
Половина евро в час
#10 
  Posmotrim знакомое лицо26.09.14 12:51
Posmotrim
NEW 26.09.14 12:51 
в ответ Murr 26.09.14 12:41
квест для Мурра:
PHP\+(.*)\[править\]

#11 
miltorg коренной житель26.09.14 13:28
miltorg
26.09.14 13:28 
в ответ Posmotrim 26.09.14 12:06
Для вашей таблицы:
$res = $mysqli->query("SELECT * FROM `table2`");
while ($row = $res->fetch_assoc()) {
$sum[$row['id']][1] = $row['value'];
$otvet[$row['id']]= $row['value'];
}
$plus=1;
while ($i++<10){
if ($plus==1){
$plus=0;
$res->data_seek(0);
while ($row = $res->fetch_assoc()) {
if ($row['parent_id'] == 0) continue;
if ($sum[$row['id']][$i]){
$sum[$row['parent_id']][$i+1]+=$sum[$row['id']][$i];// <-- Тут добавил +
$otvet[$row['parent_id']]+=$sum[$row['id']][$i];
$plus=1;
}
}
}
}
Результат:
http://fx-signal.ru/u1.php
Половина евро в час
#12 
  Posmotrim знакомое лицо26.09.14 13:31
Posmotrim
NEW 26.09.14 13:31 
в ответ miltorg 26.09.14 12:44
В ответ на:
Тут один родитель у двух - В задании такого нет.

С таким подходом до интервью врядли дойдёт дело.
#13 
miltorg коренной житель26.09.14 13:36
miltorg
NEW 26.09.14 13:36 
в ответ Posmotrim 26.09.14 13:31
80% здесь сидящих вообще не поняли про что тест - а ведь работают.
Половина евро в час
#14 
  Posmotrim знакомое лицо26.09.14 13:45
Posmotrim
NEW 26.09.14 13:45 
в ответ miltorg 26.09.14 13:28
В ответ на:
Для вашей таблицы:

#interviewer mode on
Вам сделали 4 замечания по Вашему коду, из которых одно Вы попытались оспорить, а в последствии исправить. Вдобавок допустили ещё одну ошибку.
Как Вы думаете сами, Вы нам подходите?
#interviewer mode off
#15 
miltorg коренной житель26.09.14 13:50
miltorg
NEW 26.09.14 13:50 
в ответ Posmotrim 26.09.14 13:45
Я чё был на тестировании!!!??? Я вроде в форум писал
Половина евро в час
#16 
  Posmotrim знакомое лицо26.09.14 13:51
Posmotrim
NEW 26.09.14 13:51 
в ответ miltorg 26.09.14 13:50
ну так я ведь в шутку и написал для этого "#interviewer mode on"
#17 
miltorg коренной житель26.09.14 13:53
miltorg
NEW 26.09.14 13:53 
в ответ Posmotrim 26.09.14 13:51
Тут запрещено писать не по русски
Половина евро в час
#18 
miltorg коренной житель26.09.14 15:49
miltorg
NEW 26.09.14 15:49 
в ответ miltorg 26.09.14 13:53
Насколько я понял, задание выполнено. Предлагаю связаться в скайп и обсудить детали.
С уважением
**** ********
Skype: ******
******
******
---------------------------------------
Вот так вот. Щёлкаем тесты элементарно.
Половина евро в час
#19 
  Posmotrim знакомое лицо26.09.14 15:52
Posmotrim
NEW 26.09.14 15:52 
в ответ miltorg 26.09.14 15:49
Желаю удачи.
#20 
1 2 все