Reputation: 1721
I read a great post on JOINS, What is the difference between "INNER JOIN" and "OUTER JOIN"? but I don't think it helps my issue.
I would like to combine two select statements into a single select statement AND, make it efficient for any databases to query.
Here is what I have
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'
How to shrink this SQL statement? Even if I use Inner Joins (which I'm working on), this statement is quite processor intensive (not to mention it seems really inefficient)
Upvotes: 4
Views: 557
Reputation: 23078
Building upon the providing answer, I think a more elegant solution is to hold filtering values in a separate table (separate logic from data).
However, this will work only if the conditions are disjoint (a pair of values will hit a maximum of one condition), otherwise multiple "hits" will count for more options.
CREATE TABLE dbo.AgentAndOsFilter
(
Id INT IDENTITY(1, 1),
AgentVersion VARCHAR(8),
Os VARCHAR(16)
)
This can be populated with your filtering pairs:
INSERT INTO dbo.AgentAndOsFilter (AgentVersion, Os)
VALUES ('11.%', 'Windows%'), ('12.%', 'Windows%'), ('11.%', 'Mac%'), ('12.%', 'Mac%')
The query can look like this:
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
Another advantage of this solution is changes in the configuration (new versions of agents, new operating systems) simply means changing some records in a table.
Upvotes: 2
Reputation: 93704
You can do this using Conditional Aggregate
.
Also use proper INNER JOIN
syntax to Join two tables instead of old style comma separated join. Keep the filters in Where
clause
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%'
Upvotes: 14