Вывод сразу из двух таблиц

amen666

Новичок
Здравствуйте!
Нужна помощь! Есть две таблицы:


PHP:
DATA
                `id` int NOT NULL AUTO_INCREMENT KEY,
                `objid` int NOT NULL,
                `date` date,
                `pl_min` TINYINT(1)
objects
                `id` int NOT NULL AUTO_INCREMENT KEY,
                `name` varchar(50),
                `orgname` varchar(50),
                `orient` varchar(150),
                `rating` int

В objects названия объектов, в data - записи о посещении объектов.
Нужно в итоге вывести таблицу-отчет, в которой будет число строк по числу объектов и число столбцов по числу дней, указанных юзером для формирования отчета.
Таким образом получается как бы двумерная таблица, которую нужно формировать не только по строкам, но и по столбцам. Дайте направление, как это осуществить.
 

Фанат

oncle terrible
Команда форума
ты забыл кое-что написать про свою "как бы двумерную" таблицу
что должно быть в её ячейках.

и заодно можешь написать, что ты уже пробовал.
может, из этого станет понятнее, что тебе нужно
 

amen666

Новичок
В ячейках будут плюс или минус, записываемые в поле pl_min, то есть сразу будет видно в какой день объект был посещен, а в какой - нет.
 

amen666

Новичок
Попробовал такой запрос:

PHP:
SELECT objects.id, objects.name, objects.orgname, objects.orient, objects.rating, data.objid, data.date, data.pl_min
        FROM `objects`, `data` 
        WHERE objects.id = data.objid
        ORDER BY objects.rating DESC
Но при его использовании объекты, инфа о которых заносилась в таблицу data несколько раз, дублируются в списке.
 

Фанат

oncle terrible
Команда форума
GROUP BY objid
заодно сможешь вывести циферку, сколько посещений было в день.
только pl_min вывести нельзя будет.

и не пиши ты к каждому полю её таблицу - раздувает код без всякого смысла.
Вполне можно было написать
PHP:
SELECT objid, name, orgname, orient, rating, date
кстати, а чем отличается orgname от name?
 

WMix

герр M:)ller
Партнер клуба
Но при его использовании объекты, инфа о которых заносилась в таблицу data несколько раз, дублируются в списке.
это правда, реультат обработки SQL всегда таблица, хоть даже если она состоит из 1 поля и одной строки...
зная это вдумайся сам, какой результат ты ожидаешь получить сложив 2 таблицы
 

amen666

Новичок
Действительно, если сделать одну таблицу, то можно выводить данные по дате и будет видно, какие точки в какой день были посещены.
Но мне нужен несколько другой результат. А именно - список всех или хотя бы единожды посещенных объектов, и чтобы было наглядно видно частоту их посещения за определённый срок. То есть слева будут объекты, сверху даты, в ячейках + и -, ну или 0 и 1...

name - это вывеска на магазине, orgname - юридическое название.
 

WMix

герр M:)ller
Партнер клуба
в твоем отношении поля `date` и `pl_min` будут МЕШАТЬ выбору краткой таблицы, если сгрупировать, то выбор будет случайным..
существуют груповые операторы такие как count - колличество min, max, avg.... group_concat в конце концов
"хотя бы единожды" будет звучать как
where objid is not null при использовании group by и JOIN
 

WMix

герр M:)ller
Партнер клуба
хотя соврал, WHERE objects.id = data.objid оставит только "хотя бы единожды" посещенные
 

WMix

герр M:)ller
Партнер клуба
все сделано правильно, только селекты правильно писать!
 

Фанат

oncle terrible
Команда форума
amen666
в один день могут посещаться больше одной орагнизации?
Если да, то одним запросом, наверное, не обойдёшься.
 

amen666

Новичок
Ок, добавил:

PHP:
SELECT objects.id, objects.name, objects.orgname, objects.orient, objects.rating,
				 data.objid, data.date, data.pl_min
		  FROM `objects`, `data` 
		  WHERE objects.id = data.objid
		  GROUP BY objects.id
		  ORDER BY objects.rating DESC
Объекты не дублируются, но теперь запрос не возвращает все даты - только одну для одного объекта.. Я так понимаю, должен быть ещё какой-то полезный оператор для решения данной проблемы??
 

amen666

Новичок
Фанат
Да, в один день посещаются несколько десятков организаций... Вот я тоже не могу понять, как вывести всю инфу одним запросом, да ещё и так, как надо...
 

amen666

Новичок
Сделал так:

PHP:
include 'mysql.php';

// Запрос на выборку объектов, посещённых хотя бы один раз
$query = "SELECT * FROM `objects`
		  WHERE `rating` > 1
		  ORDER BY `rating` DESC";
		  
$query = mysql_query($query);

if(!$query) echo mysql_error();



echo '<table border=1> <tr><td colspan=2 >&nbsp</td>';
$from = $_POST['from'];
$to   = $_POST['to'];

// Функция записи временного диапазона в массив
function getDateRange($from, $to)
{
$t1 = strtotime($from);
$t2 = strtotime($to) + 3600;
$dates = array();
for($i = $t1; $i <= $t2; $i += 86400)
$dates[] = date("Y-m-d",$i);
return $dates;
}
$dates = getDateRange($from, $to);

// Вывод дат диапазона в "шапку" таблицы
foreach ($dates as $dt)
{
	$dt1   = $dt[8].$dt[9].'-'.$dt[5].$dt[6].'-'.$dt[0].$dt[1].$dt[2].$dt[3];
	echo '<td>'. $dt1 .'</td>';
}
echo '</tr>';


while($row = mysql_fetch_array($query))
{
	include 'rating_table.php';
}
echo '</table>';
и rating_table.php:

PHP:
<tr>
	<td><?php echo $row['name'];?></td>
	<td><?php echo $row['orgname'];?></td>
	
	<?php foreach($dates as $dt)
		  {
				$q = "SELECT `pl_min` FROM `data`
						  WHERE `date` = $dt AND `objid` = ". $row['id'];
				$q = mysql_query($q); if(!$q) {mysql_error();}
		  
				$plus = mysql_fetch_array($q);
				echo '<td>'. $plus['pl_min'] .'</td>';
		  }
	?>
<tr>
По идее все плюсы должны расставляться, однако этого не происходит...Возможно кривой запрос в цикле??
 

WMix

герр M:)ller
Партнер клуба
PHP:
    <?php foreach($dates as $dt)
          {
                $q = "SELECT `pl_min` FROM `data`
                          WHERE `date` = $dt AND `objid` = ". $row['id'];
                $q = mysql_query($q); if(!$q) {mysql_error();}
          
                $plus = mysql_fetch_array($q);
                echo '<td>'. $plus['pl_min'] .'</td>';
          }
    ?>
это сильно... :)
может лучше сначала собрать индификаторы и создать один запрос на все
такие штуки как function getDateRange($from, $to) и все что НЕ СТРОИТ ТАБЛИЦУ вырезать в верх скрипта...
разрыв мозга просто,...
 

amen666

Новичок
Не сомневаюсь, что это будет лучше, но как это реализовать - не знаю
На счёт говнокода - после исправлю. Сейчас главное - результат, а его пока нет((

Малость отредактировал код для читабельности))
 

WMix

герр M:)ller
Партнер клуба
я с удовольствием помогу, если поможешь в чтении...

очень сложно читать сразу на 2х языках, а когда все еще и перемешанно,..
бывает что попадаются проекты, код в которых так написан, и скоблишь зубами но пишешь далеше подобную гадость, (у меня 2 детей) но ВСЕГДА начинаешь с простых поправок: все что декларация на самый верх, то что вычисления посредине, а в конце оставляешь простую разметку... а после пойск ошибок!
 

Baton

Новичок
PHP:
//debug
$_POST['from'] = '2012-10-22';
$_POST['to'] = '2012-10-23';

//объекты
$objects = array();

$r = mysql_query( "SELECT * FROM `objects`" ) or die( mysql_error() );

while ($a = mysql_fetch_assoc($r)) {
   $objects[$a['id']] = $a['name'];
}

//данные
$data = array();

//сутки
$days = array();

//Получаем данные одним запросом
$r = mysql_query("SELECT * FROM `data` WHERE `date` >= '".$_POST['from']."' AND `date` <= '".$_POST['to']."'") or die( mysql_error() );

while ($a = mysql_fetch_assoc($r)) {
   //сохраняем для вывода в html
   $days[$a['date']] = $a['date'];   
   //данные по суткам
   $data[$a['objid']][$a['date']] += $a['pl_min'];   
}

$html = '';
$html .= '<table border=1>';
$html .=    '<tr>';
$html .=       '<th>объект</th>';
foreach ($days as $day) {
   $html .=    '<th>'.$day.'</th>';
}
$html .=    '</tr>';
$html .=    '<tr>';
foreach ($data as $objid => $day_plmin) {
   $html .=    '<td>'.$objects[$objid].'</td>';
   foreach ($days as $day) {
      $html .= '<td>'.(isset($day_plmin[$day]) ? $day_plmin[$day] : 0).'</td>';
   }
$html .=    '</tr>';
}
$html .= '<table>';

echo $html;
 
Сверху