【问题标题】:Not the correct number of records (joins and cartesian) - SQL记录数不正确(联接和笛卡尔) - SQL
【发布时间】:2017-01-28 14:06:07
【问题描述】:

我正在运行 SSMS 并尝试编写一个查询以返回一个大表,该表从各种表中捕获所有数据以进行“完整市场”分析。但是,我得到的数据要么太少,要么太多。

我最大的表有 1,025,650 行。我通过这样做得到了这个号码

SELECT COUNT(*)
FROM Table_name

在我所有的桌子上。那是最大的数字。

我想要什么:如上​​所述,我想要的结果可能是包含 1,025,650 行的结果,其中包含来自不同表的多列。

我试过的:(对不起大块)

SELECT DISTINCT
    dbo.PUBACC_EN.unique_system_identifier, dbo.PUBACC_EN.call_sign, 
    dbo.PUBACC_EN.email, dbo.PUBACC_EN.phone,   
    dbo.PUBACC_EN.first_name,dbo.PUBACC_EN.last_name, 
    dbo.PUBACC_EN.entity_name, dbo.PUBACC_EN.state, 
    dbo.PUBACC_HD.radio_service_code,
    dbo.PUBACC_HD.grant_date, dbo.PUBACC_HD.last_action_date, 
    dbo.PUBACC_HD.expired_date,
    dbo.PUBACC_HD.effective_date, dbo.PUBACC_BF.buildout_date, 
    dbo.PUBACC_FR.transmitter_make, 
    dbo.PUBACC_FR.transmitter_model, dbo.PUBACC_FR.frequency_assigned,
    dbo.PUBACC_LO.lat_degrees, dbo.PUBACC_LO.lat_minutes, 
    dbo.PUBACC_LO.lat_seconds, 
    dbo.PUBACC_LO.lat_direction, dbo.PUBACC_LO.long_degrees, 
    dbo.PUBACC_LO.long_minutes, 
    dbo.PUBACC_LO.long_seconds, dbo.PUBACC_LO.long_direction 
FROM 
    dbo.PUBACC_EN
LEFT OUTER JOIN 
    dbo.PUBACC_HD ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_HD.unique_system_identifier 
LEFT OUTER JOIN 
    dbo.PUBACC_FR ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_FR.unique_system_identifier
LEFT OUTER JOIN 
    dbo.PUBACC_LO ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_LO.unique_system_identifier
LEFT OUTER JOIN 
    dbo.PUBACC_BF ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_BF.unique_system_identifier
LEFT OUTER JOIN 
    dbo.PUBACC_PA ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_PA.unique_system_identifier

以上代码返回 9,931,904 行。

然后我尝试了一个较小的查询:

SELECT DISTINCT
    dbo.PUBACC_HD.radio_service_code, dbo.PUBACC_FR.transmitter_make, 
    dbo.PUBACC_LO.lat_degrees, dbo.PUBACC_LO.lat_minutes, dbo.PUBACC_LO.lat_seconds, 
    dbo.PUBACC_LO.lat_direction, dbo.PUBACC_LO.long_degrees, dbo.PUBACC_LO.long_minutes, 
    dbo.PUBACC_LO.long_seconds, dbo.PUBACC_LO.long_direction 
FROM 
    dbo.PUBACC_EN
LEFT OUTER JOIN 
    dbo.PUBACC_HD ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_HD.unique_system_identifier 
LEFT OUTER JOIN 
    dbo.PUBACC_FR ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_FR.unique_system_identifier
LEFT OUTER JOIN 
    dbo.PUBACC_LO ON dbo.PUBACC_EN.unique_system_identifier = dbo.PUBACC_LO.unique_system_identifier

这仅返回 421,432 行。

我的问题和 TL;DR :**

我想我收到了 Cartesian Product 或者我的联接不正确。我的问题的解决方案是什么?

【问题讨论】:

  • 好吧,至少看起来unique_system_identifier不是很独特
  • 我的意思是,这很容易验证,你应该在每个表格中做一个 COUNT(DISTINCT unique_system_identifier) 并将其与 COUNT(*) 进行比较,看看它们是否是唯一的
  • 哇......这很糟糕...... 248,509 个唯一的“唯一系统标识符”......所以可以公平地说,我的问题是基于该领域缺乏唯一性的唯一性吗?
  • @MattR 这不仅仅是公平地说,它是你问题的唯一原因
  • @HartCO... 刚刚联系了我办公室的某个人... 显然这是我们的常见做法,因为我们的产品有多个使用相同标识符和呼号的记录。作为一名分析师,这让我头晕目眩。 - 我应该删除这篇文章,因为“我的”错误无法解决?

标签: sql sql-server join outer-join cartesian-product


【解决方案1】:

我认为您的查询应该使用inner joins 完成,如果您的最大行数应该在最大相关表的行数附近。至少你的描述对我来说是这样的。可能还需要使用 distinct 子句来限制您的结果。

【讨论】:

    【解决方案2】:

    您的一个表中有多行(肯定是在 PUBACC_BF PUBACC_PA 表之一),它们在“unique_system_identifier”字段中具有相同的值。

    您还想停止使用“distinct”,因为它隐藏了真正的笛卡尔,从而隐藏了查询中的错误。

    【讨论】:

      【解决方案3】:

      很明显,您的某些表中的某些 unique_system_identifier 值有多个值。如果这是一个惊喜,您将不得不深入研究各个表以找出倍数的来源。您可以在每个表上运行这样的查询以查看倍数:

      ;with cte AS (SELECT * 
                           ,COUNT(*) OVER(PARTITION BY unique_system_identifier) AS CT
                    FROM DBO.PUBACC_HD
                   )
      SELECT *
      FROM cte
      WHERE CT > 1
      ORDER BY CT DESC, unique_system_identifier 
      

      解决方法是删除意外的倍数或更改您的加入标准以确保 1:1 加入。

      【讨论】:

      • 我运行了该查询,PA 显示了 306,000 条记录,BF 表中显示了 622,00 条记录,BF 表中显示了 905,000 条记录。这是什么意思?
      • 这意味着unique_system_identifier 不是很独特。查看此查询的输出以查看是否有其他字段可能使其唯一,您可以通过将其他字段添加到COUNT(*) OVER()PARTITION BY 部分来进行测试。当查询没有返回任何记录时,您已经确定了一个唯一键。例如,可能有一个日期字段是键的一部分,您可以将上面的内容更改为:PARTITION BY unique_system_identifier,date_field 进行测试。
      猜你喜欢
      • 2013-01-15
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多