处理复杂查询

时间:2016-02-19 11:46:10

标签: sql sql-server sql-server-2008

我有以下表格及其列

  • tbAgent: - Agent,AgentX,AgentCode,NIPRNumber,PhysicalAddressState, SystemUser

  • tbBroker: - Broker,BusinessName,BrokerCode,SystemUser

  • tbCompany: - Company,CompanyX

  • tbSystemUser: - SystemUser FirstName,LastName,EmailAddress

  • tbProduct: - Product,ProductX,ProductCode,Jurisdiction,CompanyId

  • tbLicence: - 许可证,LicenceNumber,DateIssued,ExpirationDate,Jurisdiction,
    StateIssued,BrokerId,AgentId

  • tbCompanyAgent: - CompanyId,AgentId,ProductId,LicenseNumber,
    LicenseIssueDate,LicenceExpirationDate

  • tbBrokerAgent: - BrokerId,AgentId

  • 管辖权: - 司法管辖权,司法管辖区X

在这个项目中,我们分别在tbAgent,tbBroker和tbCompany存储代理商,代理商(经纪人)和公司。我们将公司的产品存储在tbProduct中。 Thr Agent的LicenseDetails存储在tbLicence中。代理商被指定给代理商(经纪人),这些细节存储在tbBrokerAgent中。 代理商也被任命为公司,这些细节存储在tbCompanyAgent中。如果公司的产品管辖权与代理许可证的居民国或非居民国匹配,则代理商被指定为公司。

请注意,代理商有两种类型的许可证存储在tbLicence中,一种是Resident,另一种是非居民许可。如果是居民许可,则列名“Jurisdiction”包含0,如果是非居民许可,则它包含实际的国家司法管辖区ID。如果它包含0,那么我们必须将Agent的PhysicalAddressState视为ResidentState。

所有司法管辖区(州)都存在于管辖区内。

现在我必须创建一个视图,我必须获取以下信息

  • CompanyX

  • 企业编码

  • BrokerX

  • BrokerCode

  • 的AgentX

  • Agentcode

  • NIPRNumber

  • 了ProductX

  • 产品代码

  • 国家

  • LicenceNumber

  • EFFECTIVEDATE

  • 到期日期

我尝试了以下查询

          SELECT a.AgentCode,sy.AgentName,L.Licence,L.LicenceNumber,DateIssued as EffectiveDate,L.ExpirationDate,J.JurisdictionX as State
  From tbAgent as a
  INNER JOIN tbLicence L ON L.AgentId=a.Agent
   LEFT OUTER JOIN (SELECT Jurisdiction,JurisdictionX FROM tbJurisdiction) as  j on j.Jurisdiction=
   (
   CASE WHEN ISNULL(L.Jurisdiction,'0')='0' THEN a.PhysicalAddressState
   ELSE
   L.Jurisdiction
   END
  )
  LEFT OUTER JOIN  (SELECT SystemUser, (FirstName + ' '+LastName) as AgentName FROM tbSystemUser ) as sy on sy.SystemUser=a.SystemUser

以上查询提取以下信息

  • 的AgentX

  • Agentcode

  • NIPRNumber

  • 国家

  • LicenceNumber

  • EFFECTIVEDATE

  • 到期日期

排除以下列

  • CompanyX

  • 企业编码

  • BrokerX

  • BrokerCode

  • 了ProductX

  • 产品代码

我无法调整上述查询来获取排除列的信息,因为查询变得越来越复杂......

请帮帮我!!!

2 个答案:

答案 0 :(得分:1)

如果问题与复杂性有关,我希望CTE技术对你来说是一个很好的建议:

;WITH cteJur as 
(
  SELECT
    Jurisdiction,
    JurisdictionX
  FROM tbJurisdiction j
),
cteSysUsr as
(
  SELECT
    SystemUser,
    (FirstName + ' '+LastName) as AgentName
  FROM tbSystemUser su
),
cteAgent as
(
  SELECT
    a.AgentCode, a.SystemUser,
    L.Licence, L.LicenceNumber,
    L.DateIssued as EffectiveDate, L.ExpirationDate,
    CASE
      WHEN ISNULL(L.Jurisdiction,'0')='0'
      THEN a.PhysicalAddressState
      ELSE L.Jurisdiction
    END as Jurisdiction
  FROM tbAgent as a
  INNER JOIN tbLicence L ON L.AgentId=a.Agent
)
SELECT
  a.AgentCode, sy.AgentName,
  a.Licence, a.LicenceNumber,
  a.EffectiveDate, a.ExpirationDate,
  J.JurisdictionX as State
FROM tbAgent as a
LEFT JOIN cteJur as j on j.Jurisdiction = a.Jurisdiction
LEFT JOIN cteSysUsr as sy on sy.SystemUser = a.SystemUser

如果您正在寻找包含“排除列”的位置 - 将它们添加到适当的CTE中并在最终选择中引用它们。您不必将每个连接的表放入子查询中。只需在选择列表中加入它和引用表的列,就是这样。正如上面的查询中所描述的那样。

答案 1 :(得分:1)

首先,您似乎对表格有很好的追随以及相关性。我试图实现它们并从相应的表中获取所有列。你可以删除任何你想要的东西。

现在,首先,我想让您查看FROM子句部分。在获取列之前,请考虑这一点,尤其是在连接的许多表的复杂查询中。把每一个带到下一个。我总是尝试使用第一个表(或别名)作为ON子句的左侧和JOINING TO作为右侧...然后,如果某些东西嵌套在第二个下面,我会保留缩进这样我就可以更直接地看到字面相关性,并且更容易混淆。

from
   FirstTable alias1
      JOIN SecondTable alias2
         on alias1.IDColumn = alias2.IDColumn
         JOIN ThirdTable alias3
            on alias2.OtherID = alias3.OtherID

现在,就你的司法管辖区而言,它有三个可能来自的地方......代理商,产品和许可证。因为我不知道您特别想要哪个版本,所以我分别对每个版本应用了LEFT-JOIN。这允许我使用不同的别名多次使用同一个表。然后我抓住每个JurisdictionX并在结果中将其称为适当的“as”名称。

最后,我构建了所有需要的字段列。如果您想缩小数据列表(例如单个代理),那么您只需应用WHERE条件。希望这很有意义,你可以删除你可能不关心的额外字段。

SELECT
      a.Agent,
      a.AgentX,
      a.AgentCode,
      a.NIPRNumber,
      a.PhysicalAddressState,
      a.SystemUser,
      ( AgUser.FirstName + ' '+ AgUser.LastName) as AgentName,
      AgUser.EmailAddress as AgentEMail,
      b.Broker,
      b.BusinessName,
      b.BrokerCode,
      b.SystemUser as BrokerUser,
      ( BrUser.FirstName + ' '+ BrUser.LastName) as BrokerName,
      BrUser.EmailAddress as BrokerEMail,
      l.License,
      l.LicenseNumber,
      l.DateIssued,
      l.ExpirationDate,
      l.Jurisdiction,
      l.StateIssued,
      ca.LicenseNumber as CA_LicenseNumber,
      ca.LicenseIssueDate as LicenseIssueDate,
      ca.LicenseExpirationDate as LicenseExpirationDate,
      c.Company,
      c.CompanyX,
      p.ProductX,
      p.ProductCode,
      AgJuris.JurisdictionX as AgentJurisdiction,
      LicJuris.Jurisdiction as LicenseJurisdiction,
      ProdJuris.Jurisdiction as ProductJurisdiction
   from
      tbAgent a
         JOIN tbSystemUser AgUser
            ON a.SystemUser = ag.SystemUser

           JOIN tbLicense l
              ON a.Agent = l.AgentID
              JOIN tbBroker B
                 ON l.BrokerID = B.BrokerID

               JOIN tbSystemUser BrUser
                  ON b.SystemUser = br.SystemUser

               LEFT JOIN tbJurisdiction LicJuris
                  ON ISNULL(L.Jurisdiction,'0') = LicJuris.Jurisdiction

         JOIN tbCompanyAgent ca
            ON a.Agent = ca.AgentID

            JOIN tbCompany c
               ON ca.CompanyID = c.Company

            JOIN tbProduct p
               ON ca.CompanyID = p.CompanyID
               AND ca.ProductID = p.Product

               LEFT JOIN tbJurisdiction ProdJuris
                  ON p.Jurisdiction = ProdJuris.Jurisdiction

         LEFT JOIN tbJurisdiction AgJuris
            ON a.PhysicalAddressState = AgJuris.Jurisdiction

此外,对于司法管辖区的问题,由于您有3个可能的问题,您可以添加最后一列,例如

COALESCE( LicJuris.Jurisdiction, AgJuris.JurisdictionX ) as WhichJurisdiction

或考虑所有3 ...

COALESCE( LicJuris.Jurisdiction, COALESCE( ProdJuris.Jurisdiction , AgJuris.JurisdictionX )) as WhichJurisdiction

因此,如果许可权限不可用,请从产品管辖区获取价值,如果不是,请回到代理商的管辖范围。