【问题标题】:Inserting CTE results into temp table generates duplicate rows将 CTE 结果插入临时表会生成重复行
【发布时间】:2018-01-13 00:21:12
【问题描述】:

我有很长的一系列 CTE,我想将结果插入到最后的临时表中。但是,我最终得到了 16 行重复数据,而不仅仅是一个。这是我的代码:

INSERT INTO #lvl_1_results
    (
        [Level_1]                       
      , [Level_0]                       
      , [P]
      , [Sim (%)]
      , [V]
      , [StAV (%)]
      , [CV]
      , [CV (%)]
      , [Sim (Mean)]
      , [SD]
      , [IAV]
      , [MAV]
      , [BMP]
      , [BMP (%)]
      , [BMV]
      , [BMV (%)]
      , [BMCV]
      , [BMCV (%)]
      , [Sim BMP (Mean)]
      , [BM SD]
      , [SAP]
      , [SAP (%)]
      , [ActV]
      , [ActV (%)]
      , [ACV]
      , [ACV (%)]
      , [Act (Mean)]
      , [Act SD]
      , [MV]
      , [MV (%)]
    )
        SELECT sc.[Level_1]
             , sc.[Level_0]
             , [P]
             , [P] / NULLIF([MV], 0)
             , [V]
             , [V] / NULLIF([MV], 0)
             , [CV]
             , [CV] / NULLIF([upper VaR], 0)
             , [Sim (Mean)]
             , [SD]
             , [IAV]
             , [MAV]
             , [BMP]
             , [BMP] / NULLIF([MV], 0)
             , [BMV]
             , [BMV] / NULLIF([MV], 0)
             , [BMCV]
             , [BMCV] / NULLIF([upper bm VaR], 0)
             , [Sim BMP (Mean)]
             , [BM SD]
             , [SAP]
             , [SAP] / NULLIF([MV], 0)
             , [ActV]
             , [ActV] / NULLIF([MV], 0)
             , [ACV]
             , [ACV] / NULLIF([upper active VaR], 0)
             , [Act (Mean)]
             , [Act SD]
             , [MV]
             , [MV] / NULLIF([parent_MV], 0)
        FROM sc
           , s_p
           , s_v
           , bm_c
           , bm_v
           , bm_p
           , a_c
           , a_v
           , a_p
           , MV
           , upper_mv
           , c_l_v
           , bm_c_l_v
           , a_c_l_v
           , s_m
           , bm_m
           , a_m
           , sim_sd
           , bm_sd
           , a_sd
           , s_i
           , s_mar

我怎样才能让这个查询只产生一行?出于性能原因,我认为我应该选择一种不仅仅选择不同行的解决方案。

【问题讨论】:

  • 您在 FROM 部分中加入了多个表,但您没有连接它们的键列。您可能拥有所有记录的笛卡尔积。
  • 从不FROM 子句中使用逗号。 始终使用正确、明确的JOIN 语法。
  • 只有 16 行?你的很多桌子都是空的。检查 LEFT JOIN 和 INNER JOIN 和 WHERE 子句,您的查询缺少它。
  • @Gordonlinoff 你提出这个建议是为了鼓励使用 left/inner/outer 并因此强制用户提供 ON 吗?因为从技术上讲,这种格式的“正确”连接语法等价物是 CROSS APPLY,它将导致完全相同的笛卡尔积。我也提倡 ansi 风格连接,只是想知道你的意图是让这个用户成为更好的编码器,因为它赢了不一定能解决他的问题(我知道你知道,但他知道吗?啊……)
  • @CaiusJard:(i) 也许是交叉连接而不是交叉应用。 (ii) 使用 INNER/LEFT/... JOIN 将强制 SQL 用户不要忘记连接条件/连接谓词:... JOIN ... ON (对于 INNER JOIN / 等是强制性的)跨度>

标签: sql sql-server common-table-expression


【解决方案1】:

正如其他人在他们的 cmets 中指出的那样,此查询不使用 ansi JOIN 语法:

TableA
[INNER/LEFT] JOIN
TableB
ON
 TableA.id=tableb.id

使用这种风格的好处是您必须提供一个 ON 子句,它迫使您考虑表中的数据实际上是如何相关的

你根本没有告诉数据库这些数据是如何相关的,所以它所做的只是将它找到的每一行连接到其他每一行,给出所有可能的行组合

因为您得到 16 行,这意味着您的某些表有 2 行或更多行。如果 2 个表有 2 行,则结果为 2x2x2x2 行。 (或者也许两个表有 2 行,一个有 4 行,或者两个表有 4 行.. 或者 2 和 8,无论哪种方式,当相乘时,每行都连接到其他行,你得到 16 行)

如果您有 2 个具有值 a、b 和 1,2 的表,并且它们像您在此处所做的那样连接,那么数据库将为您提供

a,1
a,2
b,1
b,2

这些行本身都是唯一的,但如果您只选择字母,您会看到 a a b b,然后抱怨有重复的字母。如果您只看数字,投诉将是相同的

在没有任何关系的情况下添加更多的表,它会变得更糟。希望很容易看出添加另一个带有 x 和 y 的 2 行表会将您的结果增加到 8 行..

您必须告诉您的数据库,哪些表中的哪些列将这些表链接在一起。如果您想查看哪些表导致重复,请执行 select *

【讨论】:

    猜你喜欢
    • 2015-05-03
    • 1970-01-01
    • 2014-06-03
    • 2015-11-12
    • 1970-01-01
    • 2020-01-26
    • 2017-11-03
    • 2018-07-05
    • 1970-01-01
    相关资源
    最近更新 更多