За чистый и ясный код!

Статьи на тему программирования под веб, используя PHP, MySQL, Jquery и многое другое

Работа с функцией GROUP_CONCAT()

Июнь15

Всем привет!

Хочу рассказать о работу с функцией GROUP_CONCAT.

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

Недавно мне надо было написать запрос как раз с использованием этой функции, и решил написать об этом статью.

И так, представим две таблицы, author(авторы) и books(книги авторов).

Заполним данные, ниже представлены две эти таблицы:

Таблица авторов:

CREATE TABLE `author` (
	`id` INT(10) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	`fam` VARCHAR(200) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	`birthday` DATE NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=3;

Заполняем таблицу:

INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (1, 'Николай Николаевич', 'Носов', '2008-11-23');
INSERT INTO `author` (`id`, `name`, `fam`, `birthday`) VALUES (2, 'Артур Конан', 'Дойль', '1859-05-22');

Таблица книг авторов:

CREATE TABLE `books` (
	`id` INT(10) NOT NULL AUTO_INCREMENT,
	`id_author` INT(10) NULL DEFAULT NULL,
	`book` VARCHAR(500) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
	PRIMARY KEY (`id`),
	INDEX `id_author` (`id_author`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=8;

Заполняем таблицу:

INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (1, 1, 'Незнайка учится');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (2, 1, 'Незнайка-путешественник');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (3, 1, 'Винтик, Шпунтик и пылесос');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (4, 2, 'Затерянный мир');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (5, 2, 'Шерлок Холмс');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (6, 2, 'Шерлок Холмс');
INSERT INTO `books` (`id`, `id_author`, `book`) VALUES (7, 2, NULL);

Сделаем выборки :

mysql> select * from author;
+----+-------------------------------------+------------+------------+
| id | name                                | fam        | birthday   |
+----+-------------------------------------+------------+------------+
|  1 | Николай Николаевич                  | Носов      | 2008-11-23 |
|  2 | Артур Конан                         | Дойль      | 1859-05-22 |
+----+-------------------------------------+------------+------------+
2 rows in set (0.00 sec)

mysql> select * from books;
+----+-----------+------------------------------------------------+
| id | id_author | book                                           |
+----+-----------+------------------------------------------------+
|  1 |         1 | Незнайка учится                                |
|  2 |         1 | Незнайка-путешественник                        |
|  3 |         1 | Винтик, Шпунтик и пылесос                      |
|  4 |         2 | Затерянный мир                                 |
|  5 |         2 | Шерлок Холмс                                   |
|  6 |         2 | Шерлок Холмс                                   |
|  7 |         2 | NULL                                           |
+----+-----------+------------------------------------------------+
7 rows in set (0.00 sec)

Обратите внимание, во второй выборке я специально добавил дублирующееся поле (Шерлок Холмс) и также поле с NULL записью, для чего это я сделал объясню позже.

Теперь нам надо выбрать всех авторов и их книги, если я напишу запрос

SELECT a.id, a.name, a.fam,  b.book  as books
FROM `author` a
LEFT JOIN `books` b ON a.id=b.id_author;

В итоге мы получил все книги по всем авторам:

+----+-----------------------+----------+----------------------------+
| id | name                  | fam      | books                      |
+----+-----------------------+----------+----------------------------+
|  1 | Николай Николаевич    | Носов    | Незнайка учится            |
|  1 | Николай Николаевич    | Носов    | Незнайка-путешественник    |
|  1 | Николай Николаевич    | Носов    | Винтик, Шпунтик и пылесос  |
|  2 | Артур Конан           | Дойль    | Затерянный мир             |
|  2 | Артур Конан           | Дойль    | Шерлок Холмс               |
|  2 | Артур Конан           | Дойль    | Шерлок Холмс               |
|  2 | Артур Конан           | Дойль    | NULL                       |
+----+-----------------------+----------+----------------------------+
7 rows in set (0.00 sec)

А мне бы получить записи авторов, т.е. две записи, в нашем случае, и чтобы в поле books были все книги автора…

Это можно сделать применив как раз ф-цию GROUP_CONCAT().
Схема ф-ции:

GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}
                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val])

Для того, чтобы расписать каждую из команд, я напишу пример:

mysql> SELECT a.id, a.name, a.fam, GROUP_CONCAT(DISTINCT b.book ORDER BY b.book ASC SEPARATOR ', ') AS books
    -> FROM `author` a
    -> LEFT JOIN `books` b ON a.id=b.id_author
    -> GROUP BY a.id;
+----+--------------------+-------+---------------------------------------------------------------------+
| id | name               | fam   | books                                                               |
+----+--------------------+-------+---------------------------------------------------------------------+
|  1 | Николай Николаевич | Носов | Винтик, Шпунтик и пылесос, Незнайка учится, Незнайка-путешественник |
|  2 | Артур Конан        | Дойль | Затерянный мир, Шерлок Холмс                                        |
+----+--------------------+-------+---------------------------------------------------------------------+
2 rows in set (0.05 sec)

Как видно после использование этой ф-ции я получил то, что хотел — дву строчки и в поле books все книги автора.

Теперь распишем каждую команду.
Начну с того, что группировке поддается только поле отличные от NULL, т.е. записи с содержимыми типа NULL не будет в поле books.

DISTINCT — позволяет выбрать не повторяющиеся значения, т.е. книга с дублирующим названием будет откинута, для этого я ввел дважды название книги Шерлок Холмс;
ORDER BY col_name ASC | DESC — позволяет сортировать данные;
SEPARATOR — позволяет разделить данные через нужный вам делитель, по-умолчанию это запятая «,» (без кавычек)

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

Есть еще одно ограничение. Кол-во символов которые будут отображены в сгруппированном поле по-умолчанию 1024, если надо больше, то использую переменную group_concat_max_len устанавливаем своё значение:

синатксис:
SET [GLOBAL | SESSION] group_concat_max_len = val;

пример:
SET group_concat_max_len = 2048;

Всем спасибо, в пользу тебе %username%.

Статья просмотренна 178438 раз, зашло посетителей 58984

Попробуем работу с Блогун

Июнь11

БлогунВсем привет!
Вчера я почитал, что есть Блогун.

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

Вторым условием, надо написать статью об одном из известных мировых брендов. Спрашивается, а нафик? Ну Zend я думаю есть мировой бренд, статьи на эту тематику у меня есть.

Вроде справился — в путь!

Статья просмотренна 34353 раз, зашло посетителей 7274

Работа с Zend_Session

Июнь10

Всем привет! В статье будет рассмотрено работа с сессией средствами ZendFramework.

Простейшая работ с сессией

$sess = new Zend_Session_Namespace('MyNS');

MyNS– название пространства имен, должно быть не NULL, не должен нач. с цифры и _
Если пространство имен не задано, то по умолчанию Default

Данная конструкция аналогична

$_SESSION[‘MyNS’]

Добавления данных в сессию:

$sess->someData = 'some info';    аналог $_SESSION['MyNS']['someData'] = 'some info'; 

Получение название пространства имен:

$sess->getNamespace();

Доступны магические методы

__isset(), __unset(), __get(), __set()

Расширенная работа сессий

Время жизни пространства имен

$sess = new Zend_Session_Namespace('MyNS');
$sess->someData = 'some info';

$sess->setExpirationSeconds(5, 'someData'); - время жизни ключа someData будет 5 сек
$sess->setExpirationSeconds(3); - время жизни пространства имен Dialog будет 3 сек

$sess->setExpirationHops(5 , 'someData');  - через 5 успешных обращений к ПИ (NS) someData будет удалена
$sess->setExpirationHops(3); - через 3 «прыжка» всё ПИ будет удалено

Работа с массивами в пространствах имен

$sess = new Zend_Session_Namespace('MyNS');
$sess->array = array();
$sess->array['testKey'] = 1; // Не работает в версиях ниже PHP 5.2.1

Хранение сессии в БД

Если Вы используете высоко нагруженное веб-приложение и у вас стоит несколько серверов и есть аппаратные/программные средства по контролю за нагрузкой, то каждая страница может обрабатывать разные сервера, вспомним сайт Одноклассники. Из-за этого файл сессии может быть недоступен. Для устранения такой проблемы можно использовать хранение сессии в БД.
Вообще PHP позволяет переопределить место хранения сессии, переопределить ф-ции которые отвечают за открытие, закрытие, запись и тд сессии, за это отвечает ф-ция session_set_save_handler

Вот пример использования сессии средствами Зенда:

Создаем таблицу в БД
CREATE TABLE `session` (
  `id` char(32),
  `modified` int,
  `lifetime` int,
  `data` text,
  PRIMARY KEY (`id`)
);

настраиваем Zend:

$db = DbManager::getInstance(); // тут получения объекта подключения к БД (у каждого может быть свой)
Zend_Db_Table_Abstract::setDefaultAdapter($db);

$config = array(
    'name'           => 'session',
    'primary'        => 'id',
    'modifiedColumn' => 'modified',
    'dataColumn'     => 'data',
    'lifetimeColumn' => 'lifetime'
);
 
Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config));
 
Zend_Session::start();

// дальнейшая работа с сессией

Статья просмотренна 34506 раз, зашло посетителей 8306

  

Облако тегов

cli csv dump events form Kohana locale models MySQL mysqldump orm PHP tools trigger validate газ газовый счетчик итоги кеширование переменные

Облако тегов плагина WP Cumulus для WordPress требует для просмотра Flash Player 9 или выше.

Я на твиттере!

  • у твиттера тоже бывают перерывы...

Календарь

Июнь 2010
Пн Вт Ср Чт Пт Сб Вс
« Май   Июл »
 123456
78910111213
14151617181920
21222324252627
282930  

Сейчас на сайте