具有不依赖于所有表的计数的复杂连接

时间:2014-10-24 16:06:37

标签: sql-server tsql join

我正在加入8个表来运行一个相当复杂的报告,由于数据库结构和我对多个联接的了解有限,我正在进行攻击。结构的相关部分是:

DB Schema Dia

我需要生成的报告如下所示:

DB Report Ex

到目前为止,我的所有尝试都涉及表1中的LEFT JOIN到表2-6中的每一个,表7到表6中的LEFT JOIN以及表8中的LEFT JOIN表7.我还使用表6-8尝试了INNER JOIN。我为相关表格尝试了COUNT(DISTINCT Table1ID),并且在每种情况下都SUM(CASE WHEN x THEN 1 ELSE 0 END)GROUP BY Table8Val

在每一次尝试中,我的数字太高了。在某些情况下,它们会减少几千个,而在其他情况下它们会减少几十万个。我应该如何加入这些表,以便我可以独立于大多数其他表来测试每个表?

修改

这是我尝试过的最新查询。字段/表名已被更改以保护无辜者。

SELECT  t8.T8val
        ,COUNT(DISTINCT t1.pkT1id)  AS [Main]
        ,COUNT(DISTINCT t2.fkT1id)  AS [Has t2 vals]
        ,COUNT(DISTINCT t3.fkT1id)  AS [Has t3 vals]
        ,COUNT(DISTINCT t4.fkT1id)  AS [Has t4 vals]
        ,COUNT(DISTINCT t5.fkT1id)  AS [Has t5 vals]        

FROM            Table8  t8  (NOLOCK)        
    JOIN        Table7  t7  (NOLOCK)    ON  t8.pkT8id = t7.fkT8id
    JOIN        Table6  t6  (NOLOCK)    ON  t7.pkT7id = t6.fkT7id
    LEFT JOIN   Table1  t1  (NOLOCK)    ON  t1.pkT1id = t6.fkT1id
    LEFT JOIN   Table2  t2  (NOLOCK)    ON  t1.pkT1id = t2.fkT1id                            
    LEFT JOIN   Table3  t3  (NOLOCK)    ON  t1.pkT1id = t3.fkT1id                            
    LEFT JOIN   Table4  t4  (NOLOCK)    ON  t1.pkT1id = t4.fkT1id   
    LEFT JOIN   Table5  t5  (NOLOCK)    ON  t1.pkT1id = t5.fkT1id                            

WHERE
    t8.T8val IS NOT NULL

GROUP BY T8.t8val
ORDER BY 1 ASC

编辑2

这是架构示例的a SQLFiddle。所需的输出为desired output

3 个答案:

答案 0 :(得分:1)

发生的事情是您正在创建结果集的笛卡尔积。这可能导致破坏性的性能以及不准确的结果集。我将查询分解为所有部分,然后将所有部分连接在一起以获得所需的结果集。

http://sqlfiddle.com/#!6/2c0b1/8

with Main
as (
    select t8.Table8Val,
        t6.fkTable1ID
    from Table8 t8(nolock)
    inner join Table7 t7(nolock) on t8.pkTable8ID = t7.fkTable8ID
    inner join Table6 t6(nolock) on t7.pkTable7ID = t6.fkTable7ID
    ),
T2
as (
    select t.fkTable1ID,
        count(*) count_
    from Table2 t
    group by t.fkTable1ID
    ),
T3
as (
    select t.fkTable1ID,
        t.typeId,
        count(*) count_
    from Table3 t
    group by t.fkTable1ID,
        t.typeId
    ),
T4
as (
    select t.fkTable1ID,
        count(*) count_
    from Table4 t
    group by t.fkTable1ID
    ),
T5
as (
    select t.fkTable1ID,
        count(*) count_
    from Table5 t
    group by t.fkTable1ID
    )
select m.Table8Val,
    m.fkTable1ID,
    t2_.count_ Table2Count,
    (
        select t3_.count_
        from T3 t3_
        where t3_.fkTable1ID = m.fkTable1ID
            and t3_.typeId = 1
        ) Table3Type1Count,
    (
        select t3_.count_
        from T3 t3_
        where t3_.fkTable1ID = m.fkTable1ID
            and t3_.typeId = 2
        ) Table3Type2Count,
    (
        select t3_.count_
        from T3 t3_
        where t3_.fkTable1ID = m.fkTable1ID
            and t3_.typeId = 3
        ) Table3Type3Count,
    t4_.count_ Table4Count,
    t5_.count_ Table5Count
from Main m
left join T2 t2_ on t2_.fkTable1ID = m.fkTable1ID
left join T4 t4_ on t4_.fkTable1ID = m.fkTable1ID
left join T5 t5_ on t5_.fkTable1ID = m.fkTable1ID;

此结果集也与原始问题不同。 http://sqlfiddle.com/#!6/2c0b1/7

with Main
as (
    select t8.Table8Val,
        t8.pkTable8ID,
         t6.fkTable1ID
    from Table8 t8(nolock)
    inner join Table7 t7(nolock) on t8.pkTable8ID = t7.fkTable8ID
    inner join Table6 t6(nolock) on t7.pkTable7ID = t6.fkTable7ID
    ),
T2
as (
    select t.fkTable1ID,
        count(*) count_
    from Table2 t
    group by t.fkTable1ID
    ),
T3
as (
    select t.fkTable1ID,
        t.typeId,
        count(*) count_
    from Table3 t
    group by t.fkTable1ID,
        t.typeId
    ),
T4
as (
    select t.fkTable1ID,
        count(*) count_
    from Table4 t
    group by t.fkTable1ID
    ),
T5
as (
    select t.fkTable1ID,
        count(*) count_
    from Table5 t
    group by t.fkTable1ID
    )
select result1.pkTable8ID,
    result1.Table8Val,
     count(*) Table1Count,
    sum(result1.Table2Count) Table2Count,
    sum(result1.Table3Type1Count) Table3Type1Count,
    sum(result1.Table3Type2Count) Table3Type2Count,
    sum(result1.Table3Type3Count) Table3Type3Count,
    sum(result1.Table4Count) Table4Count,
    sum(result1.Table5Count) Table5Count
from (
    select m.Table8Val,
        m.pkTable8ID,
        m.fkTable1ID,
        t2_.count_ Table2Count,
        (
            select t3_.count_
            from T3 t3_
            where t3_.fkTable1ID = m.fkTable1ID
                and t3_.typeId = 1
            ) Table3Type1Count,
        (
            select t3_.count_
            from T3 t3_
            where t3_.fkTable1ID = m.fkTable1ID
                and t3_.typeId = 2
            ) Table3Type2Count,
        (
            select t3_.count_
            from T3 t3_
            where t3_.fkTable1ID = m.fkTable1ID
                and t3_.typeId = 3
            ) Table3Type3Count,
        t4_.count_ Table4Count,
        t5_.count_ Table5Count
    from Main m
    left join T2 t2_ on t2_.fkTable1ID = m.fkTable1ID
    left join T4 t4_ on t4_.fkTable1ID = m.fkTable1ID
    left join T5 t5_ on t5_.fkTable1ID = m.fkTable1ID
    ) result1
group by result1.pkTable8ID,
    result1.Table8Val;

答案 1 :(得分:0)

如果您的数字太高,显然您正在重复数值。首先,您必须查看您的加入字段,然后确定您的选择结构与此类似(或类似),具体取决于您要汇总的字段:

SELECT 
   t0.Table8Val, --or the field you want, remember put it in the group by too
   COUNT(t1.table1ID) as NumRows, --this 
   SUM(CASE WHEN ... THEN 1 ELSE 0 END) as WhatYouWant -- or this, or what you want to aggregate
FROM
    table1 t1
    LEFT OUTER JOIN
    table2 t2 
    ON t1.XX = t2.XX [AND t1.XX = t2.XX]
    LEFT OUTER JOIN   
    table3 t3
    ON t1.XX = t3.XX [AND t1.XX = t3.XX]
    LEFT OUTER JOIN
    table4 t4 
    ON t1.XX = t4.XX [AND t1.XX = t4.XX]
    LEFT OUTER JOIN
    table5 t5 
    ON t1.XX = t5.XX [AND t1.XX = t5.XX]
    (  SELECT
         t8.Table8Val, 
         COUNT(tx.field) as CountField, --these are examples
         SUM(tx.field)as SumField 
       FROM 
       table6 t6
       LEFT OUTER JOIN
       table7 t7
       ON t6.XX = t7.XX [AND t6.XX = t7.XX]
       LEFT OUTER JOIN 
       table8 t8
       ON t6.XX = t8.XX [AND t6.XX = t8.XX]
       GROUP BY 
         t8.Table8Val )  t0
GROUP BY
  t0.Table8Val

答案 2 :(得分:-3)

这有效,我只是无法让sql小提琴工作,看起来很像#34;外部#34;加入会解决你的问题。

选择

    t8.Table8Val
    ,COUNT(DISTINCT t1.pkTable1ID) AS [Main]
    ,COUNT(DISTINCT t2.fkTable1ID) AS [Has t2 vals]
    ,COUNT(DISTINCT t3.fkTable1ID) AS [Has t3 vals]
    ,COUNT(DISTINCT t4.fkTable1ID) AS [Has t4 vals]
    ,COUNT(DISTINCT t5.fkTable1ID) AS [Has t5 vals]        

FROM            
    #Table8  t8  (NOLOCK)        
    inner JOIN        #Table7  t7  (NOLOCK)    ON  t8.pkTable8ID= t7.fkTable8ID
    inner JOIN        #Table6  t6  (NOLOCK)    ON  t7.pkTable7ID = t6.fkTable7ID
    LEFT outer JOIN   #Table1  t1  (NOLOCK)    ON  t1.pkTable1ID = t6.fkTable1ID
    LEFT outer JOIN   #Table2  t2  (NOLOCK)    ON  t1.pkTable1ID = t2.fkTable1ID                           
    LEFT outer JOIN   #Table3  t3  (NOLOCK)    ON  t1.pkTable1ID = t3.fkTable1ID                          
    LEFT outer JOIN   #Table4  t4  (NOLOCK)    ON  t1.pkTable1ID = t4.fkTable1ID  
    LEFT outer JOIN   #Table5  t5  (NOLOCK)    ON  t1.pkTable1ID = t5.fkTable1ID

WHERE
    t8.Table8Val IS NOT NULL

GROUP BY t8.Table8Val

enter image description here