Default Green Orange
Gemini_13's Blog
Блокнот полезных вещей
Home
    • Карта сайта
    • Обо мне
RSS

Генерирование таблицы с двух колонок PHP+MySQL

MySQL, Разное, Скрипты Add comments

Еще одним из интересных заданий было обработать две таблицы: товары и цены. Суть заключалась в том, что надо было составить прайс из 10к товаров, но реально товаров существовало 100к, а в таблице цен на каждый товар приходилось по 4 разные цены для каждой группы покупателей (вип, опт, розница, лучший друг и тп). Такоже небольшим нюансм было, что товары имели разный статус, пусть он для нас будет, как «в продаже/нет в наличии».

Начнем с того, какие у нас таблицы:

CREATE TABLE `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(200) NOT NULL,
  `status` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `prices` (
  `product_id` int(11) NOT NULL,
  `type` smallint(6) NOT NULL,
  `price` float(10,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

В pruducts у нас 100к записей, а в prices — 400к (100к товаров по 4 цены на каждый).

Для примера как там что выглядит два результата запроса:

MariaDB [test]> SELECT * FROM products LIMIT 8;
+----+----------+--------+
| id | name     | status |
+----+----------+--------+
|  1 | 0519f01d |      1 |
|  2 | 5e29798b |      0 |
|  3 | a6284069 |      1 |
|  4 | 91c2fa3e |      1 |
|  5 | d928535b |      1 |
|  6 | b8367e94 |      0 |
|  7 | 2fca5bd8 |      1 |
|  8 | b1df04c1 |      0 |
+----+----------+--------+
8 rows in set (0.00 sec)
MariaDB [test]> SELECT * FROM prices LIMIT 8;
+------------+------+--------+
| product_id | type | price  |
+------------+------+--------+
|          1 |    1 |  63.00 |
|          1 |    2 |  56.70 |
|          1 |    3 |  50.40 |
|          1 |    4 |  44.10 |
|          2 |    1 | 474.00 |
|          2 |    2 | 426.60 |
|          2 |    3 | 379.20 |
|          2 |    4 | 331.80 |
+------------+------+--------+
8 rows in set (0.00 sec)

Теперь по порядку, что у нас где…
products.id — уникальный ID товара
products.name — название товара
products.status — в продаже/нет в наличии
prices.product_id — ID товара
prices.type — тип цены (опт, розница, вип и тп)
prices.price — цена в неких единицах измерения

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

<?php
// Config
$cfg['host'] = "localhost";
$cfg['name'] = "test";
$cfg['user'] = "";
$cfg['pass'] = "";
$cfg['limit'] = 10000;

// Connect to DB
mysql_connect($cfg['host'], $cfg['user'], $cfg['pass']) or die ("Не могу создать соединение");
mysql_select_db($cfg['name']) or die (mysql_error());
mysql_query("set names 'utf8'");

$sql = "SELECT p.name, pr.type, pr.price
		FROM prices pr, products p
		WHERE pr.product_id = p.id
		AND p.status = 1";
$result = mysql_query($sql);

$price = array();
$y = 0;
while(($product = mysql_fetch_assoc($result)) && ($y <= $cfg['limit']))
{
	// Если такого товара нет в массиве увеличиваем счетчик товаров
	if(!$exist = array_key_exists($product['name'], $price)) $y++;

	// Убиваем обработку лишнего товара
	if($y > $cfg['limit']) break;

	$type = 'type' . $product['type'];
	// Формируем массив с именем в роли ключа и массивом цен в роли значения
	// Проверяем есть ли товар в массиве, если да, то просто дополняем его массив цен,
	// если его нет - создаем
	if($exist)
	{
		$price[$product['name']] = array_merge($price[$product['name']], array($type => $product['price']));
	}
	else
	{
		$price[$product['name']] = array($type => $product['price']);
	}
}

Теперь у нас есть один большой массив с подмассивами товаров и их цен.

Array
(
    [0519f01d] => Array
        (
            [type1] => 63.00
            [type2] => 56.70
            [type3] => 50.40
            [type4] => 44.10
        )

    [a6284069] => Array
        (
            [type1] => 465.00
            [type2] => 418.50
            [type3] => 372.00
            [type4] => 325.50
        )
    ...
)

Разбирать такой массив не сложно, вот пример:

// Разбираем массив создавая читабельный прайс (как пример)
$prices = "# | Product | Price 1 | Price 2 | Price 3 | Price 4\n";
$x=1; // Простая считалка строк для наглядности
foreach($price as $name => $prices_array)
{
	$prices .= "$x | $name | {$prices_array['type1']} | {$prices_array['type2']} | {$prices_array['type3']} | {$prices_array['type4']}\n";
	$x++;
}

// Вывод таблички
print_r("<pre>$prices</pre>");

Вот такую страницу мы получим в конечном счете (я ее немного обрежу, как никак 10к строк писать нет смысла):

# | Product | Price 1 | Price 2 | Price 3 | Price 4
1 | 0519f01d | 63.00 | 56.70 | 50.40 | 44.10
2 | a6284069 | 465.00 | 418.50 | 372.00 | 325.50
3 | 91c2fa3e | 320.00 | 288.00 | 256.00 | 224.00
.....
9998 | 0b0158a3 | 267.00 | 240.30 | 213.60 | 186.90
9999 | f529c8b4 | 788.00 | 709.20 | 630.40 | 551.60
10000 | d70b69b3 | 807.00 | 726.30 | 645.60 | 564.90

У меня эта страница генерировалась в среднем за 1,5 секунды. Кто не верит может заюзать в скрипте microtime() и лично убедится в этом.


11 июля, 2013  
Tags: mysql, php, sql, выборка

2 комментария to “Генерирование таблицы с двух колонок PHP+MySQL”

  1. dimka3210
    30 октября, 2013 at 4:16 пп

    Если кол-во цен фиксировано, то нужно было создать 4 колонки вместо 4-х строк.
    id | product_id | price1 | price2 | price3 | price4


  2. Gemini_13
    30 октября, 2013 at 5:23 пп

    Тогда было бы всё намного проще) Такое задание дали, что поделаешь.


Leave a Reply

  • Рубрики

    • FreeBSD (20)
    • Linux (46)
    • MySQL (11)
    • Windows (14)
    • Железо (3)
    • Мои моды к TorrentPier II (16)
    • Настройка сервера (49)
    • Разное (33)
    • Скрипты (30)
  • Свежие записи

    • Поля форм на Yii2: textInput(), passwordInput() и hiddenInput()
    • Поля форм на Yii2: CheckboxList()
    • SpeedTest датацентров Digital Ocean
    • Патчим Gearman на Debian
    • nginx + Apache 2.4 и REMOTE_ADDR (решение проблемы)
    • Создание и подключение swap-файла в Debian
    • Запуск PhpStorm 9 x64 на Windows
    • Рекурсивная замена прав доступа для папок и файлов в Linux
    • VirtualBox 5 + phpVirtualBox на Debian 8.2 (jessie)
    • Обработка сессий PHP с помощью Redis + phpredis на Debian 7.8
  • Ссылки

    • My GitHub
  • Архивы

    • Июнь 2016 (2)
    • Март 2016 (2)
    • Январь 2016 (3)
    • Ноябрь 2015 (2)
    • Август 2015 (1)
    • Февраль 2015 (1)
    • Январь 2015 (7)
    • Октябрь 2014 (1)
    • Июнь 2014 (1)
    • Май 2014 (1)
    • Апрель 2014 (7)
    • Февраль 2014 (9)
    • Январь 2014 (5)
    • Декабрь 2013 (7)
    • Ноябрь 2013 (1)
    • Октябрь 2013 (3)
    • Август 2013 (4)
    • Июль 2013 (4)
    • Июнь 2013 (3)
    • Апрель 2013 (2)
    • Март 2013 (2)
    • Февраль 2013 (6)
    • Январь 2013 (2)
    • Декабрь 2012 (1)
    • Ноябрь 2012 (2)
    • Октябрь 2012 (7)
    • Сентябрь 2012 (22)
Все права защищены © 2013 Gemini_13's Blog
G13.org.ua