【问题标题】:Avoiding a cross-Join避免交叉连接
【发布时间】:2011-03-09 10:48:30
【问题描述】:

我有一个查询,它计算特定客户的前缀的金额 (QTY) 的总和/计数。已使用前缀代替产品来减少版本/命名变体。

此查询在由外键链接的两个单独的表上运行,其中 client_ID 是第三个表中的共享属性和主键。一张表称为已购买,另一张称为已安装。

我正在尝试计算安装数量和购买数量之间的差异以及每个表中的一些附加字段。这个概念类似于库存检查 (Amountinstock - AmountSold)。

我遇到的问题是这会在结果上创建交叉连接。避免交叉连接的方法是什么?外部、右或左连接会解决这个问题,还是我需要使用联合语句。

表格如下:

Client  ( Client_ID*, Client) 
Purchased (Client_ID, Product, Prefix, License Status, Amount, Deployed at, Start_date, End_date) 
Installed (Client_ID, Product, Prefix, Publisher, Version, Domain, Server, Amount) 
*Primary Key 

Prefix & Client 查询码数量为:

SELECT 
    Installed.Client_ID, 
    Client.Client, 
    Installed.Prefix, 
    SUM(Installed.Amount) AS QuantityofLicensesInstalled
FROM Installed 
    INNER JOIN Client 
        ON Installed.Client_ID=Client.Client_ID
GROUP BY Installed.Client_ID, Installed.Prefix, Client.Client;

尝试加入结果的代码是:

SELECT 
    Installed.Prefix, 
    QuantityofLicensesInstalled, 
    Purchased.Prefix, 
    QuantityofLicensesPurchased, 
    (QuantityofLicensesInstalled-QuantityofLicensesPurchased) AS Differencebetweenvalues
FROM ClientIDPrefixSumInstalled, ClientIDPrefixSumPurchased;

目前正在生成交叉连接结果。

【问题讨论】:

  • 如果您关心效率,我经常发现 3 个简单的查询比 1 个复杂的查询要好。查询客户,然后是购买,然后是安装是一种选择吗?我曾经使用的另一种方法是相同的,除了我使用 UNION 如下 SELECT columnA,"" as columnB FROM TableA UNION SELECT "",columnB FROM TableB;这当然是一个过于简化的例子。
  • 当然它产生了一个交叉连接,这就是你写的。永远不要使用隐含的语法,你将永远不会再遇到这个问题。隐式连接是一种非常糟糕的编程技术。
  • 提供一些示例结果,以便我们更好地帮助您进行正确的查询。
  • 我在 Skydrive 上发布的表的示例数据和结果:cid-17aab01efe66331d.office.live.com/browse.aspx/.Public
  • 我还在 select 语句中包含了 Installed.Client_ID 和 Purchased.Client_ID 并注意查询需要匹配客户端/前缀。我是否应该使用 WHERE (Installed.Client_ID = Purchased.Client_ID) AND (Installed.Prefix = Purchased.Prefix) 之类的语句。外部联接看起来可以删除重复属性,但我在运行查询时遇到问题(使用 ACCESS 2007)。 HLGEM

标签: mysql sql database


【解决方案1】:

首先:从 select 子句和 group by 中删除 ClientIDPrefixSumPurchased 和 ClientIDPrefixSumInstalled 中的客户端列。

那么这可能会导致您需要的结果。

SELECT 
    Installed.Prefix, 
    QuantityofLicensesInstalled, 
    Purchased.Prefix, 
    QuantityofLicensesPurchased, 
    (QuantityofLicensesInstalled-QuantityofLicensesPurchased) AS Differencebetweenvalues
FROM ClientIDPrefixSumInstalled 
full outer join ClientIDPrefixSumPurchased on installed.prefix = purchased.prefix;

【讨论】:

  • 非常感谢 Jens。我无法让它立即工作,因为它似乎 MS Access 存在支持“完全外部连接”语句的问题。在 MS SQL 服务器中测试,它可以工作。再次感谢。
【解决方案2】:

获取两个表中存在的所有前缀的单个列表,获取每个表中每个前缀的总数,然后将总数左连接到前缀列表以计算差异。

SELECT
  c.Client,
  a.Prefix,
  IFNULL(i.SumAmount, 0) - IFNULL(p.SumAmount, 0) AS AmountDiff

FROM (
  SELECT Client_ID, Prefix
  FROM Installed
  UNION
  SELECT Client_ID, Prefix
  FROM Purchased
) a

  INNER JOIN Client c ON a.Client_ID = c.Client_ID

  LEFT JOIN (
    SELECT Client, Prefix, SUM(Amount) AS SumAmount
    FROM Installed
    GROUP BY Client, Prefix
  ) i
    ON a.Client_ID = i.Client_ID AND a.Prefix = i.Prefix

  LEFT JOIN (
    SELECT Client, Prefix, SUM(Amount) AS SumAmount
    FROM Purchased
    GROUP BY Client, Prefix
  ) p ON a.Client_ID = p.Client_ID AND a.Prefix = p.Prefix

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-02
    • 1970-01-01
    • 2019-05-01
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    相关资源
    最近更新 更多