SQL и 2 сложное соединение - PullRequest
0 голосов
/ 12 июля 2011

Я пытаюсь оптимизировать SQL-запрос с MySQL 5.5, в отношении 2 отдельных запросов. Я хотел бы иметь один единственный запрос в конце, если это возможно.

У меня есть таблица DocumentType (см. Схему в конце этого вопроса). Я хотел бы показать "3 DocumentInstance на 5 загружен для программы # 4", например.

Чтобы подсчитать общее количество документов на программу, у меня есть этот запрос:

select p.id as programId, count(dt.id) as totalDocPerProgram
from DocumentType dt
join DocumentTypeInProgram dtip on dtip.documentType_id=dt.id
join Program p on dtip.program_id=p.id
group by p.id

Чтобы подсчитать, сколько документов уже загружено пользователем, классифицировано программой, следующий запрос возвращает список userSession и сколько документов он загрузил ранее:

select p2.id as programId, wsc2.id as userSession, count(di2.id) as uploadedDocs
from DocumentType dt2
join DocumentInstance di2 on di2.documentType_id=dt2.id
join WebsiteCase wsc2 on di2.websiteCase_id=wsc2.id
left join Program p2 on p2.id=wsc2.program_id
group by wsc2.id

Мой вопрос: Можно ли иметь один запрос, который будет возвращаться для каждой программы, totalDocPerProgram и сколько документов уже загружено? И будет ли возможно иметь что-то вроде: «Пожалуйста, загрузите еще 2 документа для программы № 3»?

Спасибо за вашу помощь, ребята,

Nicolas

Вот сценарий определения базы данных SQL

CREATE TABLE `DocumentType` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `description` varchar(255) DEFAULT NULL,
  `lifetime` int(11) DEFAULT NULL,
  `maxDocumentSize` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


CREATE TABLE `Program` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


CREATE TABLE `DataTypeForProgram` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cardinality` int(11) DEFAULT NULL,
  `dataType_id` bigint(20) DEFAULT NULL,
  `program_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FKA6CED6BFFCC6BB96` (`program_id`),
  KEY `FKA6CED6BF17C2EE7E` (`dataType_id`),
  CONSTRAINT `FKA6CED6BF17C2EE7E` FOREIGN KEY (`dataType_id`) REFERENCES `DataType` (`id`),
  CONSTRAINT `FKA6CED6BFFCC6BB96` FOREIGN KEY (`program_id`) REFERENCES `Program` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE `WebsiteCase` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `creationDate` datetime DEFAULT NULL,
  `lastUpdate` datetime DEFAULT NULL,
  `program_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_Program` (`program_id`),
  CONSTRAINT `FK_Program` FOREIGN KEY (`program_id`) REFERENCES `Program` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE `DocumentInstance` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) DEFAULT NULL,
  `documentType_id` bigint(20) DEFAULT NULL,
  `websiteCase_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK8BE8C2F05F1A4ADE` (`documentType_id`),
  KEY `FK8BE8C2F05C57B856` (`websiteCase_id`),
  CONSTRAINT `FK8BE8C2F05C57B856` FOREIGN KEY (`websiteCase_id`) REFERENCES `WebsiteCase` (`id`),
  CONSTRAINT `FK8BE8C2F05F1A4ADE` FOREIGN KEY (`documentType_id`) REFERENCES `DocumentType` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE `DocumentTypeInProgram` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cardinality` int(11) DEFAULT NULL,
  `documentType_id` bigint(20) DEFAULT NULL,
  `program_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK190E2A0A5F1A4ADE` (`documentType_id`),
  KEY `FK190E2A0AFCC6BB96` (`program_id`),
  CONSTRAINT `FK190E2A0AFCC6BB96` FOREIGN KEY (`program_id`) REFERENCES `Program` (`id`),
  CONSTRAINT `FK190E2A0A5F1A4ADE` FOREIGN KEY (`documentType_id`) REFERENCES `DocumentType` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 0;

1 Ответ

1 голос
/ 12 июля 2011

Вы можете сделать это с помощью запроса, который объединяет ваши два существующих запроса. Вот так:

select a.programId, 
       a.totalDocPerProgram, 
       b.upLoadedDocs, 
       (a.totalDocPerProgram - b.upLoadedDocs) as remainingDocs, 
       b.userSession
from (
    select p.id as programId, 
           count(dt.id) as totalDocPerProgram
    from DocumentType dt
    join DocumentTypeInProgram dtip on dtip.documentType_id=dt.id
    join Program p on dtip.program_id=p.id
    group by p.id) a
join (
    select p2.id as programId, 
           wsc2.id as userSession, 
           count(di2.id) as uploadedDocs
    from DocumentType dt2
    join DocumentInstance di2 on di2.documentType_id=dt2.id
    join WebsiteCase wsc2 on di2.websiteCase_id=wsc2.id
    left join Program p2 on p2.id=wsc2.program_id
    group by p2.id, wsc2.id) b on a.ProgramId = b.ProgramId

Я не отлаживал это. Но такого рода вещи хорошо работают, особенно если вы включаете

 where b.userSession = constant

пункт

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...