2015-05-28 2 views
4

Я прочитал отличный пост в JOINS, What is the difference between "INNER JOIN" and "OUTER JOIN"?, но я не думаю, что это помогает моей проблеме.Упростить утверждения MS SQL

Я хотел бы объединить два оператора select в один оператор select AND и сделать его эффективным для любых запросов к базам данных.

Вот что у меня есть

SELECT 
(SELECT COUNT(*) 
         FROM dbo.sem_computer, [dbo].[V_SEM_COMPUTER], dbo.IDENTITY_MAP, dbo.SEM_CLIENT,dbo.SEM_AGENT,dbo.PATTERN 
         WHERE [dbo].[V_SEM_COMPUTER].COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND dbo.SEM_CLIENT.GROUP_ID = IDENTITY_MAP.ID 
         AND dbo.SEM_CLIENT.COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND SEM_COMPUTER.COMPUTER_ID = dbo.SEM_AGENT.COMPUTER_ID 
         AND dbo.PATTERN.PATTERN_IDX = dbo.SEM_AGENT.PATTERN_IDX 
         AND Name like '%Staten Island%' 
         AND dbo.SEM_AGENT.AGENT_VERSION LIKE '11.%' 
         AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Windows%') AS 'Windows-SEP-11', 
(SELECT COUNT(*) 
         FROM dbo.sem_computer, [dbo].[V_SEM_COMPUTER], dbo.IDENTITY_MAP, dbo.SEM_CLIENT,dbo.SEM_AGENT,dbo.PATTERN 
         WHERE [dbo].[V_SEM_COMPUTER].COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND dbo.SEM_CLIENT.GROUP_ID = IDENTITY_MAP.ID 
         AND dbo.SEM_CLIENT.COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND SEM_COMPUTER.COMPUTER_ID = dbo.SEM_AGENT.COMPUTER_ID 
         AND dbo.PATTERN.PATTERN_IDX = dbo.SEM_AGENT.PATTERN_IDX 
         AND Name like '%Staten Island%' 
         AND dbo.SEM_AGENT.AGENT_VERSION LIKE '12.%' 
         AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Windows%') AS 'Windows-SEP-12', 
(SELECT COUNT(*) 
         FROM dbo.sem_computer, [dbo].[V_SEM_COMPUTER], dbo.IDENTITY_MAP, dbo.SEM_CLIENT,dbo.SEM_AGENT,dbo.PATTERN 
         WHERE [dbo].[V_SEM_COMPUTER].COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND dbo.SEM_CLIENT.GROUP_ID = IDENTITY_MAP.ID 
         AND dbo.SEM_CLIENT.COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND SEM_COMPUTER.COMPUTER_ID = dbo.SEM_AGENT.COMPUTER_ID 
         AND dbo.PATTERN.PATTERN_IDX = dbo.SEM_AGENT.PATTERN_IDX 
         AND Name like '%Staten Island%' 
         AND dbo.SEM_AGENT.AGENT_VERSION LIKE '11.%' 
         AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Mac%') AS 'Mac-SEP-11', 
(SELECT COUNT(*) 
         FROM dbo.sem_computer, [dbo].[V_SEM_COMPUTER], dbo.IDENTITY_MAP, dbo.SEM_CLIENT,dbo.SEM_AGENT,dbo.PATTERN 
         WHERE [dbo].[V_SEM_COMPUTER].COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND dbo.SEM_CLIENT.GROUP_ID = IDENTITY_MAP.ID 
         AND dbo.SEM_CLIENT.COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
         AND SEM_COMPUTER.COMPUTER_ID = dbo.SEM_AGENT.COMPUTER_ID 
         AND dbo.PATTERN.PATTERN_IDX = dbo.SEM_AGENT.PATTERN_IDX 
         AND Name like '%Staten Island%' 
         AND dbo.SEM_AGENT.AGENT_VERSION LIKE '12.%' 
         AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Mac%') AS 'Mac-SEP-12' 

Как уменьшить этот SQL заявление? Даже если я использую Inner Joins (над которым я работаю), это утверждение достаточно интенсивно для процессора (не говоря уже о том, что оно кажется действительно неэффективным)

ответ

12

Вы можете сделать это, используя Conditional Aggregate.

Также используйте правильный синтаксис INNER JOIN, чтобы присоединиться к двум таблицам вместо старого стиля, разделенного запятой. Храните фильтры в Where пункте

SELECT Count(CASE 
       WHEN dbo.SEM_AGENT.AGENT_VERSION LIKE '11.%' 
        AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Windows%' THEN 1 
      END) AS 'Windows-SEP-11', 
     Count(CASE 
       WHEN dbo.SEM_AGENT.AGENT_VERSION LIKE '12.%' 
        AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Windows%' THEN 1 
      END) AS 'Windows-SEP-12', 
     Count(CASE 
       WHEN dbo.SEM_AGENT.AGENT_VERSION LIKE '11.%' 
        AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Mac%' THEN 1 
      END) AS 'Mac-SEP-11', 
     Count(CASE 
       WHEN dbo.SEM_AGENT.AGENT_VERSION LIKE '12.%' 
        AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE 'Mac%' THEN 1 
      END) AS 'Mac-SEP-12' 
FROM dbo.sem_computer 
     INNER JOIN [dbo].[V_SEM_COMPUTER] 
       ON [dbo].[V_SEM_COMPUTER].COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
     INNER JOIN dbo.SEM_AGENT 
       ON SEM_COMPUTER.COMPUTER_ID = dbo.SEM_AGENT.COMPUTER_ID 
     INNER JOIN dbo.SEM_CLIENT 
       ON dbo.SEM_CLIENT.COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
     INNER JOIN dbo.IDENTITY_MAP 
       ON dbo.SEM_CLIENT.GROUP_ID = IDENTITY_MAP.ID 
     INNER JOIN dbo.PATTERN 
       ON dbo.PATTERN.PATTERN_IDX = dbo.SEM_AGENT.PATTERN_IDX 
WHERE Name LIKE '%Staten Island%' 
+0

Что означает «ТОГДА 1»? Значение '1' означает TRUE? – Rhonda

+1

@SohniMahiwal - Его просто ценность для подсчета вы можете сохранить что угодно. –

2

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

Однако это будет работать только в том случае, если условия не пересекаются (пара значений будет иметь максимум одно условие), в противном случае несколько «обращений» будут учитываться для дополнительных параметров.

CREATE TABLE dbo.AgentAndOsFilter 
(
    Id INT IDENTITY(1, 1), 
    AgentVersion VARCHAR(8), 
    Os VARCHAR(16) 
) 

Это может быть заселена с парами фильтрации:

INSERT INTO dbo.AgentAndOsFilter (AgentVersion, Os) 
VALUES ('11.%', 'Windows%'), ('12.%', 'Windows%'), ('11.%', 'Mac%'), ('12.%', 'Mac%') 

Запрос может выглядеть следующим образом:

SELECT F.Id, Count(1) Cnt 
FROM dbo.sem_computer 
     INNER JOIN [dbo].[V_SEM_COMPUTER] 
       ON [dbo].[V_SEM_COMPUTER].COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
     INNER JOIN dbo.SEM_AGENT 
       ON SEM_COMPUTER.COMPUTER_ID = dbo.SEM_AGENT.COMPUTER_ID 
     INNER JOIN dbo.SEM_CLIENT 
       ON dbo.SEM_CLIENT.COMPUTER_ID = SEM_COMPUTER.COMPUTER_ID 
     INNER JOIN dbo.IDENTITY_MAP 
       ON dbo.SEM_CLIENT.GROUP_ID = IDENTITY_MAP.ID 
     INNER JOIN dbo.PATTERN 
       ON dbo.PATTERN.PATTERN_IDX = dbo.SEM_AGENT.PATTERN_IDX 
     INNER JOIN dbo.AgentAndOsFilter F 
       ON dbo.SEM_AGENT.AGENT_VERSION LIKE F.AgentVersion 
        AND dbo.SEM_COMPUTER.OPERATION_SYSTEM LIKE F.Os 
WHERE Name LIKE '%Staten Island%' 
GROUP BY F.Id 

Еще одним преимуществом этого решения является то изменения в конфигурации (новые версии агентов, новых операционных систем) просто означает изменение некоторых записей в таблице.

Смежные вопросы