SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 11.07.2010 19:34:17

nicolaus2
Участник
Зарегистрирован: 11.07.2010
Сообщений: 3

Ресурсоемкая выборка с многих таблиц

Здравствуйте, форумчане! Нужна помощь.

Есть база для хранения информации об оплате пользователями неких услуг.

Таблицы:

Years
-Year //год

Months
-id // ид месяца
-name // название месяца

Dates // тут уже связки типа год + мясяц
-id //ид даты
-yearID // год
-monthID // ид месяца

Users
-id // ид
-name // имя
-ip // ип
-mac // мак
-haveToPay // сколько должен платить

main
-userID // ид пользователя
-dateID // ид даты
-payed // сколько заплатил в некий месяц некого года


Нужно сделать выборку типа, хоть так:
Имя пользователя |янв|фев|мар|апр|май|июн|июл|авг|сен|окт|ноя|дек|
Вася                   |10 |10 |10 |10 |10 |10 |10 |10 |10 |10 |10 |10 |
Петя                   |30 |30 |30 |30 |30 |30 |30 |30 |30 |30 |30 |30 |

Тоесть сколько пользователь оплатил, статистика по месяцам определенного года.

Вот вариант, которым можно получить такую статистику, за нормальное время до, 6 месяцев(тут - 4), если больше, то работает очень медленно

Код:

select users.name, Jan.payed, Feb.payed, Mar.payed, Apr.payed from users
inner join main Jan on USERs.id = Jan.`userID`
inner join main Feb on USERs.id = Feb.`userID`
inner join main Mar on USERs.id = Mar.`userID`
inner join main Apr on USERs.id = Apr.`userID`
inner join dates date1 on (Jan.`dateID` = date1.`id` and date1.`monthID` = 1 and date1.`yearID` = 2009)
inner join dates date2 on (Feb.`dateID` = date2.`id` and date2.`monthID` = 2 and date2.`yearID` = 2009)
inner join dates date3 on (Mar.`dateID` = date3.`id` and date3.`monthID` = 3 and date3.`yearID` = 2009)
inner join dates date4 on (Apr.`dateID` = date4.`id` and date4.`monthID` = 4 and date4.`yearID` = 2009)

http://ib1.keep4u.ru/b/2010/07/11/b3/b37549a4da2d3a2908a0c837d4a117fa.jpg

Нужно получить такую выборку за сносное время. Спасибо


Таблицы

Код:

create database Users

create table Years
(
    Year numeric(4,0) primary key not null
)

create table Months
(
    id numeric(2,0) primary key not NULL,
    name varchar(20) not null
)

create table Dates
(
    id numeric(5,0) primary key not NULL,
    yearID NUMERIC(4,0) REFERENCES Years(year),
    monthID numeric(2,0) references months(id)
)

create table Users
(
    id numeric(5,0) primary key not NULL,
    name varchar(50) not null, 
    ip varchar(20) not null,
    mac varchar(20) not NULL,
    haveToPay numeric(2,0) not null
)

create table main
(
    userID numeric(5,0) references Users(ID),
    dateID numeric(5,0) references Dates(ID),
    payed numeric(4,0)
)

Неактивен

 

#2 11.07.2010 20:40:48

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Ресурсоемкая выборка с многих таблиц

А почему Вы дату храните не через DATE, а через такие странные связи?
Должно работать быстро при добавлении соответствующих индексов.

Соответствующий — это, видимо, Dates(month, year).

Неактивен

 

#3 12.07.2010 23:13:40

nicolaus2
Участник
Зарегистрирован: 11.07.2010
Сообщений: 3

Re: Ресурсоемкая выборка с многих таблиц

Знаю, было тупо.

Решилось так(удалил дурные таблицы, в main вместо dateID - номер месяца и номер года):

Код:

CREATE TABLE `main` (
  `userID` DECIMAL(5,0) primary key not NULL,
  `months` DECIMAL(5,0),
  `years` DECIMAL(5,0),
  `payed` DECIMAL(4,0)
)

CREATE TABLE `users` (
  `id` DECIMAL(5,0) NOT NULL references Users(ID),
  `name` VARCHAR(50) NOT NULL DEFAULT '',
  `ip` VARCHAR(20) NOT NULL DEFAULT '',
  `mac` VARCHAR(20) NOT NULL DEFAULT '',
  `haveToPay` DECIMAL(2,0) NOT NULL,
  PRIMARY KEY (`id`)
)

Выборка:

Код:

SELECT Users.id, Users.name, main.months, main.payed 
FROM 
    Users INNER JOIN main 
        ON Users.id=main.userID 
        where main.years = нужный год
ORDER BY main.userID, main.months

Обработка на клиенте:

Код:

    $counter = 0;
    
    echo "<table border = 1>";
    while($row=mysql_fetch_assoc($result))
     {
         if($counter == 12)
         {
             $counter = 0;
             echo "</tr>";
         }
         if($counter == 0)
         {
             echo "<tr>";
             echo "<td>";
             echo $row["name"];
             echo "</td>";
         }
         echo "<td>";
        echo $row["payed"];
        echo "</td>";
        
        $counter++;
    };
echo "</table>";

Спасибо!

Отредактированно nicolaus2 (12.07.2010 23:14:08)


Прикрепленные файлы:
Attachment Icon 55.JPG, Размер: 9,630 байт, Скачано: 331

Неактивен

 

#4 13.07.2010 16:18:15

Shopen
Гуру
Откуда: Москва
Зарегистрирован: 22.10.2007
Сообщений: 362

Re: Ресурсоемкая выборка с многих таблиц

nicolaus2 написал:

Знаю, было тупо.

Решилось так(удалил дурные таблицы, в main вместо dateID - номер месяца и номер года):

CREATE TABLE `main` (
  `userID` DECIMAL(5,0) primary key not NULL,
  `months` DECIMAL(5,0),
  `years` DECIMAL(5,0),
  `payed` DECIMAL(4,0)
)
 

Всё же что вам мешает хранить даты как даты? (`date` DATE). Если уж так хочется в разных колонках, то есть спец типы YEAR и MONTH. Кроме столбца `payed` использовать тип DECIMAL  не нужно, для месяца и года подойдет и TINYINT и даже ENUM, это же целые числа (хотя все же лучше временнЫе). userId в зависимости от количества записей какой-нибудь INT, MEDIUMINT и т.п. Кстати оно у вас сейчас уникальное, а из того как я понял вашу задачу у вас в этой таблице будет по несколько записей на пользователя.
`Payed` тоже не понятно - сумма, но без копеек?

Неактивен

 

#5 16.07.2010 16:15:08

nicolaus2
Участник
Зарегистрирован: 11.07.2010
Сообщений: 3

Re: Ресурсоемкая выборка с многих таблиц

Всё верно говорите. Сменил numeric -> TINYINT, поле года - на тип YEAR, типа MONTH не нашлось.

А по поводу primary key на userID, странно, посмотрел в базу, но primary key на нем нет. Наверное, когда писал ответ, брал запрос с первоначальной базы.

Payed - сумма оплаты за месяц без копеек.

Спасибо!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson