|
|
|
| Здравствуйте, форумчане! Нужна помощь.
Есть база для хранения информации об оплате пользователями неких услуг.
Таблицы:
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)
)
|
| |
|
|
|
|
|
|
|
для: nicolaus2
(11.07.2010 в 19:44)
| | С хранением дат, думаю, перебор.
Какие причины на такие извращения? Ведь в большинстве СУБД есть тип для хранения даты (в MySQL - это DATE).
Формирование таблицы в человекочитабельном виде - задача для обрабатывающего сценария, а не для запроса. Запрос должен заниматься выборкой, а не форматированием вывода.
Таблицы Years, Months, Dates удалить.
main.dateID удалить совсем или переименовать в date, присвоить тип даты.
Добавить целочисленное поле main.month для хранения номера месяца. Этот номер можно рассчитывать, например, так: EXTRACT(YEAR_MONTH FROM "2010-07-11").
В таблице main поставить составной индекс на поля (userID, month).
Запрос будет такой:
SELECT Users.id, Users.name, main.month, main.payed
FROM
Users INNER JOIN main
ON Users.id=main.userID
ORDER BY main.userID, main.month
|
В приложении уже извлекать результаты запроса и формировать таблицу. | |
|
|
|
|
 9.4 Кб |
|
|
для: sms-send
(11.07.2010 в 22:34)
| | Самый дельный совет из всех форумов! Спасибо!
Теперь стал более осведомлен в этом вопросе)
Решилось так(удалил дурные таблицы, в 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>";
|
http://ib1.keep4u.ru/b/2010/07/13/86/861018567b183d0b191db5cc92157bda.jpg
Спасибо! | |
|
|
|
|
|
|
|
для: nicolaus2
(12.07.2010 в 23:11)
| | и все же применять тип decimal для хранения ключевых данных
(да и вообще, в ситуации когда число цифр после точки равно нулю)
это несколько против традиций | |
|
|
|
|
|
|
|
для: Trianon
(12.07.2010 в 23:50)
| | Странно, при создании таблицы указывал тип numeric, этот код скопировал на вкладке DDL клиента EMS MYSQL | |
|
|
|
|
|
|
|
для: nicolaus2
(13.07.2010 в 01:41)
| | хрен редьки не слаще.
Int то чем не устраивает? | |
|
|
|
|