【问题标题】:How can I combine SQL queries with different expressions?如何将 SQL 查询与不同的表达式结合起来?
【发布时间】:2011-06-01 06:13:10
【问题描述】:

我的三个查询已经达到了我的 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

我怎样才能做到这一点? (如果你好奇,我要加入的真正问题如下)

感谢您的帮助!,

罗素舒特

尽我所能清理这些 - 抱歉,它们的显示效果不太好。 (这些也可能存在问题 - 它们是我 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

【问题讨论】:

    标签: sql join subquery union


    【解决方案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】:

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

    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,即如果一个地区出现在一个查询的结果中但在另一个查询中缺失。

    【讨论】:

    • 如果每个结果集没有每个 DistrictId,您可能需要 LEFT 联接或 FULL OUTER 联接。
    • 为了简洁起见,您是否考虑过为您的查询重命名表格,以便您可以键入 addlZips 之类的内容,而不是带有附加邮政编码的机构?别名信息:w3schools.com/Sql/sql_alias.asp
    • 嗨,伙计们...你统治。我问完我的问题(花了一段时间),然后跑去吃午饭......当我回来时,一切都为我想好了......我不知道我可以使用子选择作为表格然后加入他们...非常酷! @rownage,我考虑过,但我打字速度非常快,而且经常好几个月都不会检查我的代码——所以我喜欢它冗长。
    【解决方案3】:

    您将在这里获得许多答案,虽然我同意您“可以”将所有这些都集中到一个选择中,但我认为如果您愿意,您将拥有一个更容易维护和更容易运行的过程使用一些临时表或类似的东西。

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

    这样,您可以让查询继续做他们正在做的事情,并且您可以专注于最终聚合。

    您可以使用来自项目的单个查询来执行此操作,正如另一位海报提到的那样,但这可能非常难以维护。

    【讨论】:

    • 谢谢米切尔。我不熟悉临时表 - 所以你让我在谷歌上搜索以了解更多信息 - 有多用户应用程序的参考资料吗? (我不希望得到不好的结果,因为用户正在访问一堆彼此的临时表。)我本可以使用我的编程语言来引用和排序来自三个不同查询的值,这看起来像是很多开销我认为数据库可以做到。
    猜你喜欢
    • 1970-01-01
    • 2013-06-10
    • 2021-11-24
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-17
    • 2020-06-08
    相关资源
    最近更新 更多