Упростить запрос с Count из нескольких полей нескольких таблиц

ypmail
Дата: 19.01.2016 14:51:16
Считаю количество галочек (поля bit) в 4 колонках 4 таблиц по следующему запросу:
SELECT COUNT(VLabour) + COUNT(VMaterial) + COUNT(VLabourStor) + COUNT(VMaterialStor) FROM qdfLabour, qdfMaterial, qdfLabourStor, qdfMaterialStor WHERE LMainID = 990
 AND VLabour LIKE "-1" AND MMainID = 990 AND VMaterial LIKE "-1" AND LStorID = 990 AND VLabourStor LIKE "-1" AND MStorID = 990 AND VMaterialStor LIKE "-1";


Возможно ли упростить получившееся выражение?
Rivkin Dmitry
Дата: 19.01.2016 15:00:19
ypmail,

Ну, как-то так:
SELECT 4*COUNT(*)
FROM qdfLabour, qdfMaterial, qdfLabourStor, qdfMaterialStor 
WHERE LMainID = 990
 AND VLabour LIKE "-1" 
 AND MMainID = 990 
 AND VMaterial LIKE "-1" 
 AND LStorID = 990 
 AND VLabourStor LIKE "-1" 
 AND MStorID = 990 
 AND VMaterialStor LIKE "-1";


А вообще, это что за жуть? Что вычисляем, брат?
Не так
Дата: 19.01.2016 15:21:01
SELECT sum(Qnt) from (
select count(*) as Qnt from t1 where f=1
union all
select count(*)  from t2 where f=1
union all
select count(*)  from t3 where f=1
union all
select count(*)  from t4 where f=1
) t
ypmail
Дата: 19.01.2016 15:22:52
Rivkin Dmitry,

После WHERE ничего не сократить?

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

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

Сначала сделал так:
(SELECT COUNT(VLabour) FROM qdfLabour WHERE LMainID = <LMainID> AND VLabour LIKE "-1") =0 
AND (SELECT COUNT(VMaterial) FROM qdfMaterial, qdfLabour WHERE MMainID = <LMainID> AND VMaterial LIKE "-1") =0
AND (SELECT COUNT(VLabourStor) FROM qdfLabourStor, qdfLabour WHERE LStorID = <LMainID> AND VLabourStor LIKE "-1") =0
AND (SELECT COUNT(VMaterialStor) FROM qdfMaterialStor, qdfLabour WHERE MStorID = <LMainID> AND VMaterialStor LIKE "-1") =0


Потом вот так:
SELECT COUNT(VLabour) + COUNT(VMaterial) + COUNT(VLabourStor) + COUNT(VMaterialStor) FROM qdfLabour, qdfMaterial, qdfLabourStor, qdfMaterialStor WHERE LMainID = <LMainID>
 AND VLabour LIKE "-1" AND MMainID = <LMainID> AND VMaterial LIKE "-1" AND LStorID = <LMainID> AND VLabourStor LIKE "-1" AND MStorID = <LMainID> AND VMaterialStor LIKE "-1"


<LMainID> - это текущее значение, я его пока заменил конкретным, в программе записи отбираются по текущему.
ypmail
Дата: 19.01.2016 15:24:15
Не так,

Боюсь, тут много вложенных запросов, не скажется на производительности?
Rivkin Dmitry
Дата: 19.01.2016 16:22:09
ypmail,

Трудно понять задачу по невнятному куску оаисания:
автор
Вообще задумка глобальная, пока разбил задачу на части и пытаюсь её решить мелкими кусочками
Есть некая неисправность, виновником которой могут послужить работы и материалы, собственные и сторонние - соответственно 4 таблицы.
Виновником может являться только одна позиция во всех этих 4-х таблицах. Если галка уже стоит на одной позиции, то при установке её на другую, уже установленная галка затирается и выводится сообщение об этом. Такую кадабру придётся прописывать во всех 4-х таблицах через программу.

Но, если я понял правильно, подход к задаче неверный. Должно быть - таблица неисправностей (список пополняемый) И сводная таблица, допустим, с датой неисправности, кодом неисправности из талицы неисправностей и флагамиЖ сторонняя или собственная, работы или мптериалы. Тогда простым запросом с фильтром по датам можно вычислить количество неисправностей по группам: работы, материалы, сторонние, свои. И не надо ломать голову
ypmail
Дата: 19.01.2016 20:40:52
Rivkin Dmitry,

Попробую объяснить проще. Есть 4 таблицы с полями bit (значения 0 и -1, т.е. есть галочка или нет). Если в одной из таблиц эта галочка установлена, то в остальных (если она есть) должна удаляться. Дата ремонта у меня одна, ремонт один, но этот ремонт состоит из перечня собственных работ (несколько строк), сторонних (несколько строк), собственных материалов (несколько строк) и сторонних (те самые 4 таблицы). Виновником неисправности нужно обозначить только одну позицию (т.е. поставить галочку только в одной строке). Ставлю галку в одной строке любой из таблиц - во всех остальных строках и в остальных таблицах галки быть не должно, если есть - она удаляется.

В первом посте я привел выражение, по которому считаю количество галок во всех 4-х таблицах с выборкой их из базы по текущему ремонту. 990 - это ID ремонта (то же, что Вы предлагаете с датой, я делаю по ID ремонта главной таблицы), оно же в ключевых полях всех 4-х таблиц.

Пока вопрос стоит как упростить приведённое мной выражение, если в нём есть что упрощать.
Дальше будем подумать как реализовывать остальное.
__Michelle
Дата: 19.01.2016 21:45:46
ypmail
Считаю количество галочек (поля bit) в 4 колонках 4 таблиц по следующему запросу:
SELECT COUNT(VLabour) + COUNT(VMaterial) + COUNT(VLabourStor) + COUNT(VMaterialStor) FROM qdfLabour, qdfMaterial, qdfLabourStor, qdfMaterialStor WHERE LMainID = 990
 AND VLabour LIKE "-1" AND MMainID = 990 AND VMaterial LIKE "-1" AND LStorID = 990 AND VLabourStor LIKE "-1" AND MStorID = 990 AND VMaterialStor LIKE "-1";


Возможно ли упростить получившееся выражение?
Ну, хотя бы убрать все LIKE "-1", так как
во-первых, это эквивалентно равенству, но и это уже не важно, так как,
во-вторых, это эквивалентно VLabour=True, VMaterial=True и т .д., что, в свою очередь,
эквивалентно просто ... VLabour AND VMaterial AND ....

Но нормальное решение дано здесь 18701835.
Rivkin Dmitry
Дата: 20.01.2016 09:28:11
ypmail
Rivkin Dmitry,

Попробую объяснить проще. Есть 4 таблицы с полями bit (значения 0 и -1, т.е. есть галочка или нет). Если в одной из таблиц эта галочка установлена, то в остальных (если она есть) должна удаляться. Дата ремонта у меня одна, ремонт один, но этот ремонт состоит из перечня собственных работ (несколько строк), сторонних (несколько строк), собственных материалов (несколько строк) и сторонних (те самые 4 таблицы). Виновником неисправности нужно обозначить только одну позицию (т.е. поставить галочку только в одной строке). Ставлю галку в одной строке любой из таблиц - во всех остальных строках и в остальных таблицах галки быть не должно, если есть - она удаляется.

В первом посте я привел выражение, по которому считаю количество галок во всех 4-х таблицах с выборкой их из базы по текущему ремонту. 990 - это ID ремонта (то же, что Вы предлагаете с датой, я делаю по ID ремонта главной таблицы), оно же в ключевых полях всех 4-х таблиц.

Пока вопрос стоит как упростить приведённое мной выражение, если в нём есть что упрощать.
Дальше будем подумать как реализовывать остальное.

Ну, неправильно это иметь 4 таблицы на 1 ремонт! В конце-концов, сделай в таблице ремонтов кроме даты и названия еще 4 поля с описаниями и поле "галки", но не логическое, а числовое от 0 до 3: 0 - собственные работы, 1 - сторонние и т.д... Понадобится еще тип, с легкостью добавишь.
Хотя, и это неправильно. Я бы, после твоих уточнений, сделал бы справочник ремонтов (названий) - 1; Справочник неисправностей - все в кучу + флаг или тип (тип работ и тип материалов); Журнал ремонтов - дата и ID из справочника ремонтов + та самая "галка" - виновник; и последняя таблица - Деталировка ремонтов - ID из жуонала + ID из справочника неисправносетй (1 ко многим). Флаг этого ID совпадает с "галкой". Теперь считай что хочешь и как хочешь, хоть по журналу, хоть по деталировке
А 4 таблицы на один ремонт - это точно денормализация базы данных и совершенно неоправданная
ypmail
Дата: 20.01.2016 09:57:17
__Michelle
Ну, хотя бы убрать все LIKE "-1", так как
во-первых, это эквивалентно равенству, но и это уже не важно, так как,
во-вторых, это эквивалентно VLabour=True, VMaterial=True и т .д., что, в свою очередь,
эквивалентно просто ... VLabour AND VMaterial AND ....


Работает только VLabour=1.
P.S.: Правда проверял на SQL, т.к. база у меня на SQL, а интерфейс программы использует синтаксис для Access, под программу буду адаптировать позже. Думаю, в базе access будут те же результаты.

Но нормальное решение дано здесь 18701835.

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