如何将SQL查询与不同的表达式结合起来?

时间:2010-12-29 20:48:41

标签: sql join subquery union

我有三个查询已经处于我的SQL知识的最高点(Microsoft SQL 2005,如果这很重要) - 现在我需要将它们组合成一个查询,其中包含单行上的所有值。

我的实际查询如下,但我认为如果我在这里提供一个简单版本会更容易:

查询一:

-- Provides School District summary based on a CountyID
SELECT DistrictID, Count(Schools) as NumberofSchools
FROM Schools
WHERE (CountyID = 207)
GROUP BY DistrictID

查询一个示例输出:

DistrictID  |  NumberofSchools
345         |  26
567         |  17
211         |  9

查询二:

-- Summarizes Activity from our Contact Manager (GoldMine)
SELECT DistrictID, Count(Contacts) as NumberofContacts, MAX(Contact) as LastActivity
FROM ContactManager JOINED WITH CONTACT MANAGER TABLES
WHERE (CountyID = 207)
GROUP BY DistrictID

查询两个样本输出:

DistrictID  |  NumberofContacts  |  LastActivity
345         |  29                |  Nov 12, 2010
567         |  31                |  Dec 5, 2010
211         |  4                 |  Oct 9, 2010

查询三:

-- Summarizes data from our Opt-In Email Newsletter
SELECT DistrictID, Count(EmailSubscribers) AS NumberofSubscribers, MAX(Date) AS LastSent
FROM SubscribeList JOINED WITH Schools Tables
WHERE (CountyID = 207)
GROUP BY DistrictID

查询三个示例输出:

DistrictID  |  NumberofSubscribers  |  LastSent
345         |  2                    |  Sep 4, 2010
567         |  3                    |  Oct 22, 2010
211         |  1                    |  NULL

我尝试使用父SELECT语句创建一个巨大的UNION,(来自this weblink的详细信息,并为每个数据集引入SELECT NULL AS MissingColumnName)但它真的很丑 - 并且不会返回所有内容在一排。

我正在寻找这样的结果:

DistrictID  |  NumberofSchools  |  NumberofContacts  |  LastActivity  |  NumberofSubscribers  |  LastSent
345         |  26               |  29                |  Nov 12, 2010  |  2                     |  Sep 4, 2010
567         |  17               |  31                |  Dec 5, 2010   |  3                     |  Oct 22, 2010 
211         |  9                |  4                 |  Oct 9, 2010   |  1                     |  NULL

我该如何使这项工作? (如果你很好奇,我加入的真实问题就在下面)

感谢您的帮助!,

Russell Schutte

尽我所能清理这些 - 对不起,他们显示不是很好。 (这些也可能存在问题 - 它们在我的SQL知识中处于领先地位,但到目前为止,结果看似准确。): - )

查询一:

SELECT
    institutionswithzipcodesadditional_1.DistrictID, institutionswithzipcodesadditional_1.InstitutionName, institutionswithzipcodesadditional_1.Latitude, institutionswithzipcodesadditional_1.Longitude,
    SUM(CASE WHEN institutionswithzipcodesadditional.LevelID IN (4, 5, 6, 7, 8, 14, 15, 16, 20) THEN institutionswithzipcodesadditional.Enrollment ELSE 0 END) AS OthersEnrollment,
    COUNT(CASE WHEN institutionswithzipcodesadditional.LevelID IN (4, 5, 6, 7, 8, 14, 15, 16, 20) THEN institutionswithzipcodesadditional.InstitutionID ELSE NULL END) AS OthersCount, 
    SUM(CASE WHEN institutionswithzipcodesadditional.LevelID IN (13) THEN institutionswithzipcodesadditional.Enrollment ELSE 0 END) AS K12SchoolsEnrollment, 
    COUNT(CASE WHEN institutionswithzipcodesadditional.LevelID IN (13) THEN institutionswithzipcodesadditional.InstitutionID ELSE NULL END) AS K12SchoolsCount, 
    SUM(CASE WHEN institutionswithzipcodesadditional.LevelID IN (12) THEN institutionswithzipcodesadditional.Enrollment ELSE 0 END) AS HighSchoolsEnrollment, 
    COUNT(CASE WHEN institutionswithzipcodesadditional.LevelID IN (12) THEN institutionswithzipcodesadditional.InstitutionID ELSE NULL END) AS HighSchoolsCount, 
    SUM(CASE WHEN institutionswithzipcodesadditional.LevelID IN (10, 11) THEN institutionswithzipcodesadditional.Enrollment ELSE 0 END) AS MiddleSchoolsEnrollment,
    COUNT(CASE WHEN institutionswithzipcodesadditional.LevelID IN (10, 11) THEN institutionswithzipcodesadditional.InstitutionID ELSE NULL END) AS MiddleSchoolsCount,
    SUM(CASE WHEN institutionswithzipcodesadditional.LevelID IN (9) THEN institutionswithzipcodesadditional.Enrollment ELSE 0 END) AS ElementariesEnrollment,
    COUNT(CASE WHEN institutionswithzipcodesadditional.LevelID IN (9) THEN institutionswithzipcodesadditional.InstitutionID ELSE NULL END) AS ElementariesCount,
    SUM(CASE WHEN institutionswithzipcodesadditional.LevelID IN (4, 5, 6, 7, 8, 14, 15, 16, 20, 13, 12, 10, 11, 9) THEN institutionswithzipcodesadditional.Enrollment ELSE 0 END) AS AllSchoolsEnrollment, 
    COUNT(CASE WHEN institutionswithzipcodesadditional.LevelID IN (4, 5, 6, 7, 8, 14, 15, 16, 20, 13, 12, 10, 11, 9) THEN institutionswithzipcodesadditional.InstitutionID ELSE NULL END) AS AllSchoolsCount
FROM zipcodes 
    INNER JOIN users_link_territory ON zipcodes.CountyID = users_link_territory.CountyID
    INNER JOIN institutionswithzipcodesadditional ON zipcodes.ZIP = institutionswithzipcodesadditional.ZIP
    RIGHT OUTER JOIN institutionswithzipcodesadditional AS institutionswithzipcodesadditional_1 ON institutionswithzipcodesadditional.DistrictID = institutionswithzipcodesadditional_1.InstitutionID
WHERE
    (institutionswithzipcodesadditional_1.CountyID = 207)
AND (institutionswithzipcodesadditional_1.LevelID IN (1, 2, 3, 6, 7, 8))
GROUP BY institutionswithzipcodesadditional_1.DistrictID, institutionswithzipcodesadditional_1.InstitutionName, institutionswithzipcodesadditional_1.Latitude, institutionswithzipcodesadditional_1.Longitude

查询二:

SELECT
institutionswithzipcodesadditional_1.InstitutionID AS DistrictID,
COUNT(GoldMine.dbo.CONTACT1.ACCOUNTNO) AS GM,
MAX(CASE WHEN GoldMine.dbo.CONTHIST.USERID NOT IN ('DEBRA', 'TRISH', 'RUSSELL', 'GREG') THEN GoldMine.dbo.CONTHIST.OnDate ELSE NULL END) AS LastActivity
FROM institutionswithzipcodesadditional
    LEFT OUTER JOIN contacts
    LEFT OUTER JOIN GoldMine.dbo.CONTACT1
    RIGHT OUTER JOIN GoldMine_Link_Russell 
    ON GoldMine.dbo.CONTACT1.KEY3 = GoldMine_Link_Russell.GoldMineKeyThree
    ON contacts.ContactID = GoldMine_Link_Russell.ContactID 
    ON institutionswithzipcodesadditional.InstitutionID = contacts.InstitutionID
    RIGHT OUTER JOIN institutionswithzipcodesadditional AS institutionswithzipcodesadditional_1
    ON institutionswithzipcodesadditional.DistrictID = institutionswithzipcodesadditional_1.InstitutionID
    LEFT OUTER JOIN GoldMine.dbo.CONTHIST ON GoldMine.dbo.CONTHIST.ACCOUNTNO = GoldMine.dbo.CONTACT1.ACCOUNTNO
WHERE (institutionswithzipcodesadditional_1.CountyID = 207) AND (institutionswithzipcodesadditional_1.LevelID IN (1, 2, 3, 6, 7, 8))
GROUP BY institutionswithzipcodesadditional_1.InstitutionID

查询三:

SELECT
COUNT(NewsletterContacts.Email) AS EMailableContacts,
institutionswithzipcodesadditional_1.InstitutionID AS DistrictID,
MAX(newsletterregister.Sent) AS LastSent
FROM newsletterregister
    RIGHT OUTER JOIN contacts ON newsletterregister.ContactID = contacts.ContactID
    RIGHT OUTER JOIN institutionswithzipcodesadditional ON contacts.InstitutionID = institutionswithzipcodesadditional.InstitutionID
    LEFT OUTER JOIN EmailableContacts ON institutionswithzipcodesadditional.InstitutionID = EmailableContacts.InstitutionID
    RIGHT OUTER JOIN institutionswithzipcodesadditional AS institutionswithzipcodesadditional_1 ON 
    institutionswithzipcodesadditional.DistrictID = institutionswithzipcodesadditional_1.InstitutionID
WHERE
    (institutionswithzipcodesadditional_1.CountyID = 207)
    AND (institutionswithzipcodesadditional_1.LevelID IN (1, 2, 3, 6, 7, 8))
GROUP BY institutionswithzipcodesadditional_1.InstitutionID

3 个答案:

答案 0 :(得分:4)

是的,你可以使用连接来做到这一点:

SELECT
    T1.DistrictID,
    T1.NumberofSchools,
    T2.NumberofContacts,
    T2.LastActivity,
    T3.NumberofSubscribers,
    T3.LastSent
FROM (SELECT ...) T1
JOIN (SELECT ...) T2 ON T1.DistrictID = T2.DistrictID
JOIN (SELECT ...) T3 ON T1.DistrictID = T3.DistrictID

(SELECT ...)是三个原始查询的占位符。如果三个查询可以返回不同的区域,也可以考虑使用OUTER JOIN,即如果一个区域出现在一个查询的结果中但在另一个查询中丢失了。

答案 1 :(得分:1)

我偷了Mark的解决方案的一部分,但我想告诉你这个布局的可读性。这样,您就不会将所有三个查询都塞进一个select语句中。这为您提供了一些可以通过临时表或表变量获得的可维护性优势,但是下面的更改更灵活,因为每次添加/删除列时都不必乱用表声明。

With SomeGoodName as
(
  SELECT ...
)
,
AnotherDescriptiveName as
(
  Select ...
)
,
AThirdNiceName as
(
  Select ...
)
SELECT
    T1.DistrictID,
    T1.NumberofSchools,
    T2.NumberofContacts,
    T2.LastActivity,
    T3.NumberofSubscribers,
    T3.LastSent
FROM SomeGoodName T1
JOIN AnotherDescriptiveName T2 ON T1.DistrictID = T2.DistrictID
JOIN AThirdNiceName T3 ON T1.DistrictID = T3.DistrictID

答案 2 :(得分:0)

你会在这里得到一些答案,虽然我同意你“可以”把这一切都整理成一个选择,但我认为你将会有一个更容易维护和更容易运行的过程,如果你使用一些临时表或类似的工作。

例如,创建临时表来存储三个查询中的每个查询的结果,然后将三个临时表连接在一起以获取最终结果并在之后销毁临时表。

通过这种方式,您可以使查询保持正在执行的操作,并且您可以专注于最终聚合。

你可以使用单独的查询来完成这项工作,就像另一张海报所提到的那样,但这很难维护。