Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Разбор массива после запроса с объединением таблиц
 
 автор: куч1963   (12.04.2010 в 02:30)   письмо автору
27.1 Кб
 
 

После левого объединения получилась таблица, дамп которой привожу.
Как мне стоит разобрать лучше разобрать массив

<?php
for ($base=array(); $row=mysql_fetch_assoc($ctg); $base[]=$row);

?>


чтобы получить данные в таком табличном формате
st_name | e_data - e_name - e_type |e_data1 - e_name1 - e_type1 |

Иванов | score | score |
петров | score | score |

  Ответить  
 
 автор: Trianon   (12.04.2010 в 03:35)   письмо автору
 
   для: куч1963   (12.04.2010 в 02:30)
 

Вы бы сам запрос привели...

  Ответить  
 
 автор: куч1963   (12.04.2010 в 07:19)   письмо автору
 
   для: Trianon   (12.04.2010 в 03:35)
 

То, что я прикрепил в файле есть результат от объединения этих таблиц запросом


CREATE TABLE IF NOT EXISTS `event` (
  `id_event` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `pos` smallint(3) unsigned NOT NULL DEFAULT '0',
  `hide` enum('show','hide') NOT NULL DEFAULT 'show',
  `type` enum('T','L','K','Z','E') NOT NULL DEFAULT 'T',
  `id_plan` smallint(6) unsigned NOT NULL,
  PRIMARY KEY (`id_event`),
  KEY `sort_id` (`id_plan`),
  KEY `id_plan` (`id_plan`),
  KEY `type` (`type`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251;


CREATE TABLE IF NOT EXISTS `score` (
  `student_id` int(10) unsigned NOT NULL,
  `id_group` tinyint(3) unsigned NOT NULL,
  `id_event` int(10) unsigned NOT NULL,
  `score` text NOT NULL,
  `data` date NOT NULL,
  `id_prepod` int(10) unsigned NOT NULL,
  PRIMARY KEY (`id_event`,`student_id`),
  KEY `student_id` (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=cp1251;


CREATE TABLE IF NOT EXISTS `students` (
  `student_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `sex` enum('f','m') NOT NULL,
  `id_group` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`student_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=cp1251;



Собственно сам запрос

SELECT 
  students.name AS st_name,
  event.name AS e_name,
  event.`type` As e_type,
  score.score AS score,
  score.`data` AS e_data
FROM
  students
 INNER JOIN event
 LEFT JOIN score 
ON students.student_id = score.student_id 
              AND event.id_event = score.id_event
WHERE
  students.id_group = 11 AND 
  event.id_plan = 49 
ORDER BY
  event.pos, event.id_event ";



Левое соединение применено сознательно для получения полной выборки по таблице event

  Ответить  
 
 автор: Trianon   (12.04.2010 в 09:40)   письмо автору
 
   для: куч1963   (12.04.2010 в 07:19)
 

students
INNER JOIN event
Это как ?
полное декартово произведение?

  Ответить  
 
 автор: куч1963   (12.04.2010 в 10:15)   письмо автору
 
   для: Trianon   (12.04.2010 в 09:40)
 

Практически так и выходит. Мне нужно выбрать все события из таблицы event и выбрать всех из таблицы students.
Структура вывода по горизонтали:
1 строка: Ф.И.О /событие1/событие2/././включая те, которые не произошли
послед. стр. Фамилия/результат события1/результат2/

  Ответить  
 
 автор: Trianon   (12.04.2010 в 11:26)   письмо автору
 
   для: куч1963   (12.04.2010 в 10:15)
 

Так может просто нужно ORDER BY добавить определенности?
ORDER BY students.name, students.students_id, event.pos, event.id_event 

Ну и дальше цикл по всем записям.
Данные будут предоставлены сугубо в порядке формирования ячеек HTML-таблицы.
Левый заголовок строки с именем студента (и конечно закр тег предыдущей) выводить в момент смены student_id.

  Ответить  
 
 автор: куч1963   (12.04.2010 в 11:50)   письмо автору
 
   для: Trianon   (12.04.2010 в 11:26)
 

Так конечно лучше, только вот не доходит, как правильно сформировать первую строку.
По идее
[code]
<table>
<tr><td>F.I.O</td><td>событие 1</td><td>событие 2</td>.....</tr>
<tr><td>name</td><td>score 1</td><td>score 1</td>.....</tr>
/code]
Получается что, нужно за первый проход цикла формировать 1 строку, а затем возвращаться обратно, и уже формировать данные?

  Ответить  
 
 автор: Trianon   (12.04.2010 в 12:45)   письмо автору
 
   для: куч1963   (12.04.2010 в 11:50)
 

первую строку можно сформировать либо до цикла, либо, что более естественно - по флагу отсутствия заголовка.
Можно также применить предпросмотр набора результата на строку вперед, хотя по-моему это уже излишне.

  Ответить  
 
 автор: куч1963   (12.04.2010 в 13:33)   письмо автору
 
   для: Trianon   (12.04.2010 в 12:45)
 

Что-то я совсем с флагами запутался. Это флаг надо ставить не только на отсутствие, но и на наличие?
Туплю совсем:((.
Репа уже не соображает. Что я не так делаю, в этом коде?

$flag ="";
echo "<table>";
$i=0;
while ($row=mysql_fetch_assoc($ctg))
{
if($flag != $row['e_name'])
{
if($i ==0)
{
echo "<tr><td>ФИО</td>";
++$i;
}
echo "<td>".$row['e_name']."</td>";
$flag=$row['e_name'];
}

}



Как правильно поставить флаги? не могу дойти своим мозогом.

  Ответить  
 
 автор: Trianon   (12.04.2010 в 20:39)   письмо автору
 
   для: куч1963   (12.04.2010 в 13:33)
 

в этом коде Вы в первую очередь не так расставили отступы.
Полагаю, сделав это непреднамеренно.
Потому что преднамеренная публикация кода без отступов выглядит, как плевок.

  Ответить  
 
 автор: куч1963   (12.04.2010 в 22:05)   письмо автору
 
   для: Trianon   (12.04.2010 в 20:39)
 

Вы совершенно правы в том, что такая публикация кода была сделана неосознанно.
Вот, что получилось в результате творчества.
Вроде все работает, только хотелось бы прочесть ваше мнение о реализации.

<?php
                                                         
//Объявляю два массива для контроля элементов
$flag = array ();
$flag1 = array ();

echo 
"<table border=1>";
                                                      
$i 0;                                         //Объявляю переменную для вывода первой строки первого столба

while ($row mysql_fetch_assoc($ctg)) {
    if (!
in_array($row['e_name'], $flagtrue)) {
        if (
$i == 0) {
            echo 
"<tr><td>ФИО</td>";
            ++
$i;
        }

        echo 
"<td>" $row['e_name'] . "</td>";

        
$flag[] = $row['e_name'];
    } elseif (
in_array($row['e_name'], $flagtrue)) {
        if (!
in_array($row['student_id'], $flag1true)) {
            echo 
"</tr><tr><td>" $row['st_name'] . "</td>";

            
$flag1[] = $row['student_id'];
        }

        echo 
"<td>";

        if (empty(
$row['score'])) {
            echo 
"&nbsp;";
        } else {
            echo 
$row['score'];
        }

        echo 
"</td>";
    }
}

echo 
'</table>';
?>


  Ответить  
 
 автор: Trianon   (12.04.2010 в 22:40)   письмо автору
 
   для: куч1963   (12.04.2010 в 22:05)
 

кошмар.
Сделать флаг - фактически идентификатор текущего студента - массивом?
Такое разбазаривание ресурсов я не видел очень давно.

<?

echo "<table>\r\n";
$flag ''// студент не открыт
while ($row mysql_fetch_assoc($ctg))
{
    if(
$flag != $row['stud_id']) // ситуация нового студента
    
{
        if(
$flag !== ''// при открытом старом
            
echo "</tr>\r\n";
        
$flag $row['stud_id']
        
printf("<tr id=\"st_%d\"><th>"%s"</th>\r\n",
                
$flaghtmlspecialchars($row['stud_name']) );
    }
    
printf("  <td>"%s"<td> <td>"%s"<td> <td>"%s"<td>\r\n",
            
htmlspecialchars($row['score_date']),
            
htmlspecialchars($row['event_name']),
            
htmlspecialchars($row['event_type']) );
}
if(
$flag !== '')     //если студент остался открыт
    
echo "</tr>\r\n";
echo 
"</table>\r\n";

  Ответить  
 
 автор: куч1963   (12.04.2010 в 23:07)   письмо автору
 
   для: Trianon   (12.04.2010 в 22:40)
 

А как мне теперь видоизменить, чтобы получить в первой строке

<?
echo "<table>\r\n"
echo 
"<tr><td>F I O</td><td>".htmlspecialchars($row['event_name'])."</td> \r\n"

и закрыть первую строку?

  Ответить  
 
 автор: Trianon   (12.04.2010 в 23:31)   письмо автору
 
   для: куч1963   (12.04.2010 в 23:07)
 

внесите правку в тот оператор, что под условием.

  Ответить  
 
 автор: куч1963   (12.04.2010 в 23:57)   письмо автору
 
   для: Trianon   (12.04.2010 в 23:31)
 

Нужно добавлять еще одно условие и флаг?
Сейчас пробую это сделать на вашем примере, не выходит.


if($flag1 != $row['id_event']) // новая строка
    {
        if($flag1 !== '') // при открытом старом
            echo "</tr>\r\n";
        $flag1 = $row['id_event'];
        printf("<tr id=\"ev_%d\"><th>\"%s\"</th>\r\n", $flag1, "FIO" );
    
    }
    printf("  <td>\"%s\"</td>\r\n",htmlspecialchars($row['e_name']));




как закрыть его, и передать дальше

  Ответить  
 
 автор: Trianon   (12.04.2010 в 23:59)   письмо автору
 
   для: куч1963   (12.04.2010 в 23:57)
 

Зачем еще одно условие?
У Вас на одного студента несколько событий?

Вы приведите пример выдачи, так чтобы можно было понять сколько каких строк откуда выводится.


PS.А впрочем, лучше не приводите.

  Ответить  
 
 автор: куч1963   (13.04.2010 в 00:10)   письмо автору
 
   для: Trianon   (12.04.2010 в 23:59)
 

Вы наверное устали объяснять мне прописные истины, но к сожалению - трудно доходит:((
Вывод должен быть таким:
первая строка:
ФИО/событие1/событие2/.....</tr>
name/оценка1/оценка2/...</tr>

Я благодарен Вам, за то, что потратили на объяснение свое время.

  Ответить  
 
 автор: Trianon   (13.04.2010 в 01:01)   письмо автору
 
   для: куч1963   (13.04.2010 в 00:10)
 

а вторая?
а третья?
А второй третий студенты?
name это имя события или имя студента?
если имя события, то что такое событие1, 2 и так далее?
если имя студента, то что такое ФИО?
1, 2 это нумерация сквозная или внутри одного студента?

Вы издеваетесь.

Теперь, впрочем, я устал объяснять и этот последний тезис тоже.

  Ответить  
 
 автор: куч1963   (13.04.2010 в 02:04)   письмо автору
12.1 Кб
 
   для: Trianon   (13.04.2010 в 01:01)
 

Я не прав. Нарисовал, как это должно выглядеть. Событие - название темы занятия.

PS уметь объяснить, что ты хочешь, может далеко не всякий.

  Ответить  
 
 автор: Trianon   (13.04.2010 в 09:23)   письмо автору
 
   для: куч1963   (13.04.2010 в 02:04)
 

Да уж. В жизни бы не догадался.
Знаете, что Вы не сделали?
Вы не обвели жирным шапку Вашей таблицы. Не показали, что это отдельный поток данных.
Нет ничего зазорного в том, чтобы вытащить данные шапки отдельным - более простым запросом.
Уж коль скоро Вам все равно нужно все события показывать, а не только те, по которым оценки имеются.

И там не нужна будет возня с флагами.

PS. Хотеть больше, чем умеешь выразить - хотеть лишнего.

  Ответить  
 
 автор: куч1963   (13.04.2010 в 10:24)   письмо автору
 
   для: Trianon   (13.04.2010 в 09:23)
 

Я всегда внимательно разбираю ваши советы и приведенные решения.
В том коде, что Вы привели, есть всё необходимое для решения моей задачи.
Правда флаг пришлось поставить, и собрать в одну переменную первую строку, все остальное в другую.
Получилось так.

<?
$flag 
''// студент не открыт
$roll_st="";
$zag_td ="";
$break_1_row=0;
while (
$row mysql_fetch_assoc($ctg))
{
    if(
$flag != $row['student_id']) // ситуация нового студента
    
{
        if(
$flag !== ''){ // при открытом старом
        
$zag_td .="</tr>\r\n";
            
$roll_st .=  "</tr>\r\n";
            
$break_1_row=1;
            }
        
$flag $row['student_id'];
        if(
$break_1_row==0){
        
$zag_td .= sprintf("<tr><th>\"%s\"</th>\r\n""FIO" );
                }
        
$roll_st .= sprintf("<tr id=\"st_%d\"><th>\"%s\"</th>\r\n",
                
$flaghtmlspecialchars($row['st_name']) );
                
    }
    if(
$break_1_row==0){
    
$zag_td .=  sprintf("  <td>\"%s\"</td>\r\n",$row['e_name'] );
    }
    
$roll_st .= sprintf("  <td>\"%s\"</td>\r\n"$row['score']);

}

echo    
$zag_td;
    
echo    
$roll_st;
if(
$flag !== '')   //если студент остался открыт
    
echo "</tr>\r\n";
echo 
"</table>\r\n"


Наверняка, снова есть косяки, но все выводит как надо. Огромное спасибо за разъяснения и помощь в решении этой задачи. Даже в принципе, если учитывать тот факт, что в html не предъявляется особых требований к закрывающим /tr, то можно еще дальше модифицировать:))
PS К сожалению, при общении с людьми, мы мало уделяем внимания тому факту, что логика мышления у людей разная.

  Ответить  
 
 автор: Trianon   (13.04.2010 в 10:38)   письмо автору
 
   для: куч1963   (13.04.2010 в 10:24)
 

так, в принципе, тоже можно.
Попробуем разобрать плюсы и минусы.
плюсы: один запрос вместо двух
минусы: Сильно осложненная логика алгоритма, запутанный код, и самое главное - необходимость накапливать выходной поток в переменных.. А значит - изрядные требования к скрипту по памяти.
Впрочем, еще один плюс -- этот вариант Вы самостоятельно не только реализовали, но и придумали.

PS. Основная цель моей деятельности на этом портале - делиться логикой мышления с другими людьми. Вернее даже - менять эту логику.
PPS. Я оценил, насколько аккуратно Вы отвечаете.

  Ответить  
 
 автор: куч1963   (13.04.2010 в 11:15)   письмо автору
 
   для: Trianon   (13.04.2010 в 10:38)
 

И еще один вопрос в эту тему.
Почему в запросе, если писать
FROM
  students
 INNER JOIN event

То запрос проходит, а если
FROM
  students,  event

То выдается ошибка. Ведь по сути эти записи эквивалентны?

  Ответить  
 
 автор: Trianon   (13.04.2010 в 11:48)   письмо автору
 
   для: куч1963   (13.04.2010 в 11:15)
 

JOIN может иметь условие ON
а CROSS JOIN ( или запятая) - не может. По сути смысла.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования