Модераторы: LSD

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Группировка данных в запросе 
:(
    Опции темы
Depeche_14
Дата 23.5.2005, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



При помощи GROUP BY в результирующем наборе данных группируются записи по одинаковому значению столбца или столбцов. Т.е. образуется как бы подгруппа в результирующем наборе данных. При помощи COUNT можно подсчитать элементы этой подгруппы. Это мне понятно. А вот как сделать так, чтобы получившиеся подгруппы сгруппировать в подгруппы более высокого уровня? Т.е. к примеру, есть предметы сделанные из следующих материалов: алюминия, железа, чугуна, сосны, березы, бука (6 подгрупп). Их можно объединить в предметы, которые сделаны из металла (1-ая подгруппа) и из дерева (2-ая подгруппа), но при этом нужно посчитать все предметы, сделанные из металла. И отдельно все предметы, сделанные из дерева. Вот как это реализовать с помощью SQL-запроса? Надеюсь, понятно объяснил ситуацию. Заранее благодарен.
PM MAIL   Вверх
Golden Hands
Дата 23.5.2005, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Золотой
****


Профиль
Группа: Участник Клуба
Сообщений: 2023
Регистрация: 23.1.2005
Где: Екатеринбург

Репутация: 1
Всего: 83



Используй Where.


--------------------
Мы обречены... но только на победу!
Настанет день, и мы построим новый дом.
Внесем в него тепло, что сохранить сумели,
И воскресим все то, что в нас когда-то умерло... © Тень Света
PM MAIL ICQ   Вверх
Akina
Дата 24.5.2005, 08:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 13
Всего: 454



Цитата(Depeche_14 @ 24.5.2005, 00:35)
есть предметы сделанные из следующих материалов: алюминия, железа, чугуна, сосны, березы, бука (6 подгрупп). Их можно объединить в предметы, которые сделаны из металла (1-ая подгруппа) и из дерева (2-ая подгруппа), но при этом нужно посчитать все предметы, сделанные из металла. И отдельно все предметы, сделанные из дерева.

Во-первых, должны быть данные, позволяющие идентифицировать запись как относящуюся к группе "металлические" или там "деревянные" - причем это может быть как отдельное поле (SubstanceID), так и группа внутри поля (MaterialID = SubstanceID & MaterialNum).
Во-вторых, в запросе может быть только одна группировка (вложенные запросы - не в счет). И, соответственно, групповые операции только по этому типу группировки.

Это теория... что до практики - дай структуру таблицы, потому как из описания не понять, что тебе мешает...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Depeche_14
Дата 24.5.2005, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



Цитата(Akina @ 24.5.2005, 08:10)
Это теория... что до практики - дай структуру таблицы, потому как из описания не понять, что тебе мешает...

На самом деле дело вот в чем: делаю программу приема платежей за электроэнергию. В кратце объясню суть. Есть лицевой счет. Он присваивается человеку,который платит за электроэнергию. Этот человек зарегистрирован (прописан) по определенному адресу. Кроме этого человека на этом же адресе могут быть прописаны другие люди, которые могут пользоваться льготами по оплате электроэнергии. Есть четыре категории льгот: 1- Ветераны ВОВ, 2- Инвалиды ВОВ, 3- Вдовы, 4- Узники концлагерей. В программе необходимо формировать отчеты по количеству льготников на лицевых счетах. Т.е. на таком-то лицевом счете такой-то льготой пользуются столько-то человек. Это я решил с помощью GROUP BY - группирую по номеру лицевого счета и виду льготы, а потом подсчитываю количество человек при помощи COUNT.
Проблема вот в чем: при вычислении самого платежа необходимо учитывать вот что. Виды льгот группируются в две группы: 1- Ветераны ВОВ + Инвалиды ВОВ. Для данной группы неважно, сколько человек пользуются данными видами льгот. Расчеты выполняются как для одного человека. 2- Вдовы + Узники концлагерей. А вот для этой группы необходимо для алгоритма начисления платежа посчитать количество человек, пользующихся льготами этой группы. Вот как это реализовать мне непонятно. Я пытался упростить с помощью "Деревяшек" и "железяк", а то для объяснения слишком сложно получается. Но уж если никак... А структура таблиц такая: 1- ЛичныеДанные с полями КОД, ЛицевойСчет, ФИО и т.д. 2- Льготники с полями КОД, ЛицевойСчет (для связи с таблицей ЛичныеДанные), ФИО, ВидЛьготы (значения берутся из таблицы-справочника Льготы). 3- Льготы с полями КОД, Название (название льгот). Вот как тут быть, подскажите, насколько возможно.
PM MAIL   Вверх
Akina
Дата 24.5.2005, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 13
Всего: 454



Давай рассуждать.

Базовой для организации связей у тебя является таблица льготников, к ней привязаны льготы и счета в соотношении много-к-одному.

Строим первый запрос, включая в него только таблицы льготников. В этом запросе мы можем сделать группировку по ИД лицевого счета, отбор по номеру льготы и посчитать COUNT (допустим что Вдовы имеют ID=2, а узники ID=3):
Код
Select ЛицевойСчет, Count(ВидЛьготы) From Льготники Group By ЛицевойСчет Where ВидЛьготы In (2, 3);

Строим второй запрос, все то же, определяем просто наличие ветеранов (ID=0) и инвалидов (ID=1)
Код
Select ЛицевойСчет, 1 From Льготники Group By ЛицевойСчет Where ВидЛьготы In (0, 1);

Полученные запросы связываем с таблицей лицевого счета. Обеспечиваем вывод в не имеющих соответствия полях выборки нуля вместо пустого значения. Это ты уж сам...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Depeche_14
Дата 26.5.2005, 01:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



Построил запросы, всё прекрасно. Как раз то, что нужно. Вопрос возникает при связывании запроса с таблицей личных данных. Вот, что я делал: открываю схему данных, добавляю туда запрос (в нем 2 столбца: ЛицевойСчет и Количество - кол-во человек на данном лицевом счете по одной из групп льготников). Затем перетаскиваю ЛицевойСчет из запроса на ЛицевойСчет таблицы личных данных, открывается окно "Изменение связей", нажимаю "Создать". Создается связь, но каких-либо обозначений (один-ко-многим, много-к-одному и т.п.) нет. Далее, как я понимаю, в таблицу личных данных нужно добавить столбец, в котором должно указываться искомое число льготников (из запроса для данного лицевого счета). В конструкторе добавляю в эту таблицу столбец. В типе данных выбираю "Мастер подстановок", далее выбираю "Объект "столбец подстановки" будет использовать значение из таблицы или запроса". Потом выбираю свой запрос и из него выбираю поле "Количество". "Вылазит" окошко "Создание подстановки", в котором: "Automation error. Не найден указанный модуль". (Все эти манипуляции выполняю ессно в Access). Что не так делаю?
PM MAIL   Вверх
Akina
Дата 26.5.2005, 08:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 13
Всего: 454



Цитата(Depeche_14 @ 26.5.2005, 02:29)
Создается связь, но каких-либо обозначений (один-ко-многим, много-к-одному и т.п.) нет.

и правильно

Цитата(Depeche_14 @ 26.5.2005, 02:29)
Далее, как я понимаю, в таблицу личных данных нужно добавить столбец

не правильно понимаешь, в таблицу ничего не добавляется, получается просто еще один запрос.

Цитата(Depeche_14 @ 26.5.2005, 02:29)
В типе данных выбираю "Мастер подстановок" [skipped]

Это все - лишнее.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Depeche_14
Дата 26.5.2005, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



Огромное спасибо!
PM MAIL   Вверх
Depeche_14
Дата 29.5.2005, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



Цитата(Akina @ 24.5.2005, 12:56)
Обеспечиваем вывод в не имеющих соответствия полях выборки нуля вместо пустого значения.

Почему-то в запросе выводятся только те лицевые счета, где есть две группы льготников. Т.е. если на лицевом счете льготник, относящийся только к одной группе, то в запросе он не выводится. Пытался решить этот вопрос с помощью инструкции Iif, но почему-то не получается. Все равно выводятся только те лицевые счета, где есть две группы льготников. Как сделать так, чтобы отображались все лицевые счета, где есть льготники?

PM MAIL   Вверх
Akina
Дата 30.5.2005, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 13
Всего: 454



Цитата(Depeche_14 @ 29.5.2005, 14:40)
в запросе выводятся только те лицевые счета, где есть две группы льготников

Значит ты используешь inner join вместо outer join


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Depeche_14
Дата 30.5.2005, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



Да, действительно. Вместо OUTER JOIN использовал INNER JOIN. С инструкцией INNER JOIN код SQL этого запроса выглядел так:

SELECT ЛичныеДанные.ЛицевойСчет, ЛичныеДанные.ФИО, IIF(ISNULL([50проц]),0,[50проц]) AS 50_проц, IIF(ISNULL([27кВт]),0,[27кВт]) AS 27_кВт
FROM Запрос_50 INNER JOIN (Запрос_27 INNER JOIN ЛичныеДанные ON Запрос_27.ЛицевойСчет=ЛичныеДанные.ЛицевойСчет) ON Запрос_50.ЛицевойСчет=ЛичныеДанные.ЛицевойСчет;

Вместо INNER везде поставил RIGHT, получилось то что хотел, код выглядит в результате так:

SELECT ЛичныеДанные.ЛицевойСчет, ЛичныеДанные.ФИО, IIf(IsNull([50проц]),0,[50проц]) AS 50_проц, IIf(IsNull([27кВт]),0,[27кВт]) AS 27_кВт
FROM Запрос_50 RIGHT JOIN (Запрос_27 RIGHT JOIN ЛичныеДанные ON Запрос_27.ЛицевойСчет = ЛичныеДанные.ЛицевойСчет) ON Запрос_50.ЛицевойСчет = ЛичныеДанные.ЛицевойСчет;

У меня просьба: растолкуйте смысл инструкций INNER JOIN и OUTER JOIN на каком-нибудь примере. Теоретически-то я знаю, что INNER JOIN объединяет записи из двух таблиц, если связующие поля этих таблиц содержат одинаковые значения. И ее синтаксис выглядит следующим образом:
FROM таблица_1 INNER JOIN таблица_2 ON таблица_1.поле_1 оператор таблица_2.поле_2
Но тут эти инструкции как бы вложены друг в друга... Вот я смысл не могу уловить. Запрос составлял в конструкторе запросов Access.
Та же самая беда и с инструкцией OUTER JOIN. Общий синтаксис (как я понимаю) для внешнего соединения имеет следующий вид:
FROM ТАБЛИЦА1 {RIGHT | LEFT | FULL} JOIN ON ТАБЛИЦА2
а у меня так же "вложенный" вариант. И почему запрос начал работать как надо только при RIGHT JOIN, а при LEFT и FULL не работал?
PM MAIL   Вверх
Akina
Дата 31.5.2005, 08:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 13
Всего: 454



Цитата(Depeche_14 @ 31.5.2005, 00:10)
растолкуйте смысл инструкций INNER JOIN и OUTER JOIN на каком-нибудь примере.

Пример:

Открываем Аксесс.
Делаем новую БД.
Делаем 2 таблицы, в каждой 2 поля, поле ID - строка, но НЕ КЛЮЧЕВОЕ, и поле Str - тож строка. Ключевого поля не делаем.
Заполняем таблицы. В каждой по 4 записи. Значения ID для первой таблицы: (1, 2, 3, не заполнено), для второй таблицы: (не заполнено, 2, 3, 4). Для поля Str значения типа (Таб1Стр1, Таб1Стр2, ...).
Создаем запрос в конструкторе. Туда - обе таблицы. Отбор - всех полей. Делаем связь между полями ID. Меняем объединение (каждый из 3 возможных) и каждый раз смотрим результат выборки. Можно перевести в режим SQL и опробовать все варианты Join (простой, Inner, Outer, Left, Right, Full).


А можно просто прочитать встроенную справку.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Depeche_14
Дата 1.6.2005, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



Понятно. Спасибо большое.
Вот теперь есть у меня запрос, который выдает количество льготников по категориям для определенного лицевого счета. Мне нужно создать форму для вычисления платы за пользование электроэнергией (и я такую форму создаю). Т.е., к примеру, в ней поля: номер лицевого счета, дата, количество киловатт, требуется оплатить рублей - в этом поле выводится результат. Т.к. в алгоритме расчета результата необходимо учитывать количество льготников по категориям, то эту форму создаю на основе полученного запроса, вношу еще в нее поля, в которых отображается количество льготников на данном лицевом счете, ну и у меня все вычисляется. Особенность данной формы в том, что вычисленное значение никуда не записывается. Его (значение) просто нужно видеть оператору для того, чтобы сказать клиенту, сколько денег нужно платить в кассу.
Думаю, что из-за своей неопытности в вопросах программирования БД делаю не совсем рационально. К примеру, в этой форме расчета платежа необязательно видеть количество льготников (можно св-во Visible соответствующих полей формы установить False).
А можно сделать форму расчета платежа просто "саму по себе" не на основе полученного запроса, но в алгоритме расчета платежа использовать данные из запроса для конкретного лицевого счета? Если да, то как? Если не трудно, хотя бы основные направления подскажите, пожалуйста.
PM MAIL   Вверх
Akina
Дата 2.6.2005, 08:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 13
Всего: 454



Цитата(Depeche_14 @ 1.6.2005, 23:37)
А можно сделать форму расчета платежа просто "саму по себе" не на основе полученного запроса, но в алгоритме расчета платежа использовать данные из запроса для конкретного лицевого счета? Если да, то как? Если не трудно, хотя бы основные направления подскажите, пожалуйста.

Конечно можно. Но в этом нет никакого смысла - это фактически выполнить на клиенте работу, которую должна выполнять серверная часть (БД).


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Depeche_14
Дата 2.6.2005, 23:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 23.1.2005

Репутация: нет
Всего: нет



Понял, в очередной раз спасибо. Просто хотел узнать как программно обратиться к запросу (ну или к таблице), чтобы из определенной записи (именно той, которая нужна) выбрать значение конкретного поля (полей), т.к. в изучении подобных вопросов без примеров самостоятельно трудно продвинуться.
Да, вот еще такой вопрос: когда в форме с одного на другое поле передается фокус, значение (число или текст) в получившем фокус поле выделяется черным цветом. Можно ли как-нибудь избежать вот такого "выделения"? Ну чтобы получение полем фокуса как-нибудь по-другому обозначалось.
Спасибо.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Общие вопросы по базам данных"
LSD
Zloxa

Данный форум предназначен для обсуждения вопросов о базах данных не попадающих под тематику других форумов:

  • вопросам по СУБД для которых нет отдельных подфорумов
  • вопросам которые затрагивают несколько разных СУБД (например проблема выбора)
  • инструменты для работы с СУБД
  • вопросы проектирования БД
  • теоретически вопросы о СУБД

Данный форум не предназначен для:

  • вопросов о поиске разлиных БД (если не понимаете чем БД отличается от СУБД то: а) вам не сюда; б) Google в помощь)
  • обсуждения проблем с доступом к СУБД из различных ЯП (для этого есть соответсвующие форумы по каждому ЯП)
  • обсуждения проблем с написание SQL запросов, для этого есть форум Составление SQL-запросов
  • просьб о написании курсовой, реферата и т.п., для этого есть Центр помощи или фриланс биржа
  • объявлений о найме специалистов, для этого есть раздел Объявления о найме специалистов

Если вы не соблюдаете эти правила, не удивляйтесь потом не найдя свою тему/сообщение. ;)


Полезные советы:

При написании сообщения постарайтесь дать теме максимально понятное название. В теме максимально подробно опишите проблему. Если применимо укажите: название базы данных и версии (MySQL 4.1, MS SQL Server 2000 и т.п.); используемых язык программирования; способа доступа (ADO, BDE и т.д.); сообщения об ошибках.

Для вставки кода используйте теги [code=sql] [/code].

Литературу по базам данных можно поискать здесь.

Действия модераторов можно обсудить здесь.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, LSD, Zloxa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | СУБД, общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0758 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.