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

Форум MySQL

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

 

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

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

тема: многотабличный запрос
 
 автор: lilu   (08.10.2007 в 12:56)   письмо автору
 
 

помогите пож. составить запрос :

есть 4 таблицы, вот их структура:
programma {id_prog, name_prog}
например {1, программа1; 2, программа 2; 3, программа 3}

voprosy{id_vopr, name_vopr}

tema{id_tema, name_tema}

full{id, id_prog, id_tema, id_vopr}

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

<?
$query2 
"SELECT * FROM programma"
  
$sub2 mysql_query($query2,$db); 
  if(!
$sub2) exit(mysql_error()); 
  echo 
"<select name='sel_prog' size='1'>";
  while(
$tmp mysql_fetch_array($sub2)) 
  { echo 
"<option>$tmp[name_progr]</option><br>";
   } echo 
"</select>";    
?><input name="perehod" type="submit" value="перейти">

   
 
 автор: EXP   (08.10.2007 в 17:17)   письмо автору
 
   для: lilu   (08.10.2007 в 12:56)
 

>, после чего на экране должны вывестись соответствующие ей темы и в каждой вопросы.

непонятно что находится в таблице full и как узнатть какие темы соответствуют выбранной программе ,
и какие вопросы соответствуют теме соответствующей выбранной программе?

например перейдёт пользователь на страницу "script.php?sel_prog=1",
по ссылке сгенерированной в форме

 <?
while($tmp mysql_fetch_array($sub2))  
  { 
   echo 
"<option value='$tmp[id_prog]'>$tmp[name_prog]</option>\n"
   } 

и что ему надо показать ? названия тем и вопросов с такими-же id ? если в трёх таблицах содержатся только айди и имена

   
 
 автор: lilu   (09.10.2007 в 09:21)   письмо автору
 
   для: EXP   (08.10.2007 в 17:17)
 

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

Есть темы конечно специфические согласно специальности, но у всех есть и общие темы, например -"Общее положение о предприятии", "Коллективный договор", "Техника безопасности" и т.д.
Что касается вопросов, то например в теме "Техника безопасности" для экономистов не должны быть вопросы касающиеся специфики работы монтёров (такие как - работы на высоте и т.д.).

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

   
 
 автор: EXP   (09.10.2007 в 15:00)   письмо автору
 
   для: lilu   (09.10.2007 в 09:21)
 

мне и самому интересно как правильнее такое организовать :)
можно всё сделать вообще на одной таблице , только незнаю можно-ли такое делать :)
если таких программ так немного ,
можно средствами php организовать что-то типа array(0 =>'человек без профессии', 1 =>'монтёр', 2 =>'бухгалктер', 3 =>'экономист');
и обойтись двумя таблицами,
если необязательно на каждой странице напоминать монтёрам название их профессии
а просто использовать получаемый id :)
непроверял но должно работать даже и такое

<?php
$query_szdtbl1 
"CREATE TABLE voproses (
  id_v int(11) NOT NULL AUTO_INCREMENT, " 
// порядковые номера вопросов (необязательно)
  
"name_v text NOT NULL, " // название каждого (необязательно)
  
"body_v text NOT NULL, " // само содержание вопроса
  
"theme_id int(5) NOT NULL, " // id темы к которой относится
  
"profes enum(0, 1, 2, 3) NOT NULL default 0, " // профессия читателя
  
"date datetime NOT NULL default '0000-00-00 00:00:00', " // время добавления (необязательно)
  
"PRIMARY KEY  (id_v) " //  (необязательно)
  
") TYPE=MyISAM;";
?>
            ВТОРАЯ ТАБЛИЦА
<?php
$query_szdtbl2 
"CREATE TABLE t_names (
  id_t int(5) NOT NULL AUTO_INCREMENT, // номера тем
  name_t text NOT NULL, // названия тем
  profes enum(0, 1, 2, 3) NOT NULL default 0, // профессия читателя
  PRIMARY KEY  (id_v) 
  ) TYPE=MyISAM;"
;
?>
            ВЫБРАТЬ НАЗВАНИЯ ТЕМ ДЛЯ ПРОФЕССИИ МОЖНО ТАК
<?php
$query_them 
'SELECT id_t, name_t FROM t_names (
  WHERE profes = ' 
. (int)$_GET['sel_prog'] . ';';

            
## ИЛИ ВЫБРАТЬ ВОПРОСЫ ПО ТЕМАМ С НАЗВАНИЕМ ТЕМЫ ##
            
$query 'SELECT id_v.voproses, name_v.voproses, body_v.voproses, date.voproses,
  name_t.t_names
  FROM voproses LEFT JOIN t_names
  ON profes.voproses = ' 
. (int)$_GET['sel_prog'] . '
  AND theme_id.voproses = ' 
$thema = (int)$_GET['thema'] . 
  AND id_t.t_names = ' 
$thema 
  GROUP BY id_v.voproses;'
// наверное

// НЕУДОБНО ТЕМ ЧТО С КАЖДЫМ ВОПРОСОМ ВОЗВРАЩАЕТ СНОВА НАЗВАНИЕ ТЕМЫ

## ИЛИ ВЫБРАТЬ НАЗВАНИЯ ТЕМ И ВОПРОСОВ ##
            
$query 'SELECT name_v.voproses, name_t.t_names
  FROM voproses LEFT JOIN t_names
  ON profes.voproses = ' 
. (int)$_GET['sel_prog'] . '
  AND theme_id.voproses = ' 
$thema = (int)$_GET['thema'] . 
  AND id_t.t_names = ' 
$thema 
  GROUP BY id_v.voproses;'
;
?>

я ещё не волшебник я только учусь )
хотелось-бы знать как-же такое правильно организуется

// или просто делать несколько запросов к MySQL в этих файлах

// наверное там где enum(0, 1, 2, 3) профессия 0 , не безработный , а для всех профессий,
надо только тогда поменять условие в выборке на profes.voproses = ' . (int)$_GET['sel_prog'] . ' OR profes.voproses = 0

   
 
 автор: EXP   (09.10.2007 в 21:41)   письмо автору
 
   для: EXP   (09.10.2007 в 15:00)
 

одной таблицей имел ввиду вот.так )

<?php
$query_create_tbl 
'CREATE TABLE x_table ( '
  
'id int(11) NOT NULL AUTO_INCREMENT, '// порядковые номера рядов (необязательно)
  
'chto enum(\'proff\', \'tema\', \'vopros\') NOT NULL default "vopros", ' // что-за вообщче ряд :)
  
'context_id int(5) NOT NULL, ' // идентификационный ключ тем и проффессий
  
'otnosh tinytext NOT NULL, ' // строка с указанием идентификаторов тем к каким относится вопрос например через пробел '0 3 4'
  
'dopusk tinytext NOT NULL, ' // строка с ключами имеющих допуск к чтению вопросов и тем например через пробел '0 3 4'
  
'body text NOT NULL, ' // содержимое
  
'date datetime NOT NULL default \'0000-00-00 00:00:00\', ' // время добавления (необязательно)
  
'PRIMARY KEY  (id) ' //  (необязательно)
  
') TYPE=MyISAM;';
?>
            ВЫБРАТЬ НАЗВАНИЯ ТЕМ ДЛЯ ПРОФЕССИИ
<?php

$query_them 
'SELECT id  body FROM x_table
  WHERE chto="tema" 
  AND LOCATE("' 
. (int)$_GET['sel_prog'] . '", dopusk) NOT 0;';
            
            
#  ВОПРОСЫ ПО ТЕМЕ
            
$query_vop 'SELECT id  body FROM x_table
  WHERE chto="vopros" AND LOCATE("' 
. (int)$_GET['thema'] . '", otnosh) NOT 0 
  AND LOCATE("' 
. (int)$_GET['sel_prog'] . '", dopusk) NOT 0;';

            
/*  ВЫБРАТЬ ВОПРОСЫ ПО ТЕМАМ 
            С НАЗВАНИЕМ ТЕМЫ И НАЗВАНИЕМ ПРОФЕСИИ :)
            и тоже повторяются много раз названия */
            
$query "SELECT id, 
  CONCAT_WS('', '', (SELECT body FROM x_table
    WHERE context_id =" 
. (int)$_GET['sel_prog'] . 
    AND chto='proff')) AS proff, 
  CONCAT_WS('', '', (SELECT body FROM x_table
    WHERE chto="
tema
    AND context_id =" 
. (int)$_GET['thema'] . ")) AS thema
FROM x_table
WHERE chto="
vopros" AND LOCATE('" . (int)$_GET['thema'] . "', otnosh) != 0 
AND LOCATE('" 
. (int)$_GET['sel_prog'] . "', dopusk) != 0;";
?>
даже если последний запрос будет из разных таблиц , возвращаемый результат весит на порядок больше чем нужно , поэтому
наверное проще сделать несколько запросов к базе, но говорят что их лучше когда меньше

   
 
 автор: EXP   (10.10.2007 в 06:11)   письмо автору
 
   для: EXP   (09.10.2007 в 15:00)
 

раз никто непоправляет , примерно так делается выбор из трёх таблиц без повтора одних и тех-же значений :)

CREATE TABLE mesg (
  id_mesg int(7) NOT NULL AUTO_INCREMENT,
  time datetime NOT NULL default '0000-00-00 00:00:00',
  dop tinytext NOT NULL,
  otnosh tinytext NOT NULL,
  body text NOT NULL,
  PRIMARY KEY  (id_mesg)
  ) TYPE=MyISAM;

INSERT INTO mesg (time,
 dop, otnosh,
   body)
 VALUES ( NOW(),
  '0', '0',
   'вопрос для всех , показывается во всех разделах'), ( NOW(),
  '2 3', '2',
   'вопрос для модеров и админов такой показывается только в разделе с айди 2'), 
   ( NOW(),
  '1', '1 3',
   'вопрос для юзеров показывается в разделе с айди 1 и 3');


CREATE TABLE users (
  id_users int(7) NOT NULL AUTO_INCREMENT,
  id_dop int(2) NOT NULL default '0',
  name VARCHAR(25) NOT NULL,
  pswrd tinytext NOT NULL,
  status enum('user', 'moder', 'admin') NOT NULL default 'user',
  UNIQUE KEY (name),
  PRIMARY KEY  (id_users)
  ) TYPE=MyISAM;


INSERT INTO users (name, id_dop, pswrd, status) VALUES ('admin', 3,
   MD5('admin'),
     'admin'), ('moder', 2,
   MD5('moder'),
     'moder'), ('user', 1,
   MD5('user'),
     'user');

CREATE TABLE razd (
  id_razd int(7) NOT NULL AUTO_INCREMENT,
  id_otnosh int(5) NOT NULL default '0',
  dop tinytext NOT NULL,
  r_name text NOT NULL,
  PRIMARY KEY  (id_razd)
  ) TYPE=MyISAM;

INSERT INTO razd (id_otnosh, dop, 
 r_name)
 VALUES (1, '0',
   'раздел для всех'), 
   (2, '2 3', 'раздел для модеров и админов'), 
   (3, '1', 'раздел для юзеров');
<?
// ВЫБОР ВОПРОСОВ РАЗДЕЛОВ И ЮЗЕРОВ ) 
$status = (isset($_GET['status'])) ? (int)$_GET['status'] : ;
$razd = (isset($_GET['razd'])) ? (int)$_GET['razd'] : ;
$vop = (isset($_GET['vop'])) ? (int)$_GET['vop'] : ;

$sql "(SELECT id_users, name, (@dop := id_dop) AS df FROM users 
            WHERE status=
$status )
            UNION ALL
            ( SELECT id_razd, r_name, (@otn := id_otnosh) AS of 
            FROM razd 
            WHERE id_razd=
$razd 
            AND ((LOCATE(@dop, dop) != 0) OR (LOCATE('0', dop) != 0)) ) 
            UNION ALL
            ( SELECT id_mesg, body, 0 
            FROM mesg 
            WHERE ((LOCATE(@dop, dop) != 0) OR (LOCATE('0', dop) != 0))
            AND ((LOCATE(@otn, otnosh) != 0)  OR (LOCATE('0', otnosh) != 0)) LIMIT 0, 30 );" 
// &#237;&#224;&#239;&#240;&#232;&#236;&#229;&#240; :)
$result m_query($sql);
while(
$line mysql_fetch_array($resultMYSQL_ASSOC))
{
var_dump($line);
}
?>

только там вместо бухгалтеров модеры :)

вот и думать потом из чего лучше выбрать приходится выбирая между понятным и не очень )
насчёт работоспособности такого способа не уверен :)

   
Rambler's Top100
вверх

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