SQL Server改进

时间:2013-03-11 19:26:50

标签: sql sql-server sql-server-2005

这个查询目前的功能我想要它的工作方式,但我的善良似乎是一个巨大的错误。它基本上是3个查询连接在一起并排序。我一遍又一遍地使用相同的逻辑,我希望有更好的方法来写这样的东西?

有没有办法不反复使用相同的选择逻辑?我可以以某种方式消除必须连接3次?

select z1.description, z0.* from (
select 
    p0.Id,
    p0.[NetworkCompliant],
    p0.[NetworkNonCompliant],
    p0.[PercentageNetworkCompliant],
    p0.[PercentageNetworkNonCompliant],
    p1.[USNNetworkCompliant],
    p1.[USNNetworkNonCompliant],
    p1.[USNPercentageNetworkCompliant],
    p1.[USNPercentageNetworkNonCompliant],
    p2.[USMCNetworkCompliant],
    p2.[USMCNetworkNonCompliant],
    p2.[USMCPercentageNetworkCompliant], 
    p2.[USMCPercentageNetworkNonCompliant]
from (
select 
    t1.id as [Id], 
    SUM(case when t0.compliant = 1 then 1 else 0 end) as [NetworkCompliant],
    SUM(case when t0.compliant = 0 then 1 else 0 end) as [NetworkNonCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 1 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    end as [PercentageNetworkCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 0 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    end as [PercentageNetworkNonCompliant]
from lineitemsmap as t0
    inner join lineitems as t1 on t1.id = t0.lineitemid
    inner join art_blob as t2 on t2.art_blob_id = t0.blobid
    inner join art_asset as t3 on t3.art_asset_id = t2.art_asset_id and t3.decommissioned = 0    
    inner join net_ou as t4 on t4.NET_OUID = t3.NET_OUID
    left outer join lineitemexceptions as t5 on t5.assetid = t3.art_asset_id and t5.lineitemid = t1.id
where t5.AssetId is null
group by t1.id
) as p0
left outer join (
select 
    t1.id as [Id], 
    SUM(case when t0.compliant = 1 then 1 else 0 end) as [USNNetworkCompliant],
    SUM(case when t0.compliant = 0 then 1 else 0 end) as [USNNetworkNonCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 1 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    end as [USNPercentageNetworkCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 0 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    end as [USNPercentageNetworkNonCompliant]
from lineitemsmap as t0
    inner join lineitems as t1 on t1.id = t0.lineitemid
    inner join art_blob as t2 on t2.art_blob_id = t0.blobid
    inner join art_asset as t3 on t3.art_asset_id = t2.art_asset_id and t3.decommissioned = 0 
    inner join net_ou as t4 on t4.NET_OUID = t3.NET_OUID
    left outer join lineitemexceptions as t5 on t5.assetid = t3.art_asset_id and t5.lineitemid = t1.id
where t4.NET_EnclaveID = 2 and t5.AssetId is null  
group by t1.id
) as p1 on p1.Id = p0.id

left outer join 
(
select 
    t1.id as [Id], 
    SUM(case when t0.compliant = 1 then 1 else 0 end) as [USMCNetworkCompliant],
    SUM(case when t0.compliant = 0 then 1 else 0 end) as [USMCNetworkNonCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 1 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    end as [USMCPercentageNetworkCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 0 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    end as [USMCPercentageNetworkNonCompliant]
from lineitemsmap as t0
    inner join lineitems as t1 on t1.id = t0.lineitemid
    inner join art_blob as t2 on t2.art_blob_id = t0.blobid
    inner join art_asset as t3 on t3.art_asset_id = t2.art_asset_id and t3.decommissioned = 0 
    inner join net_ou as t4 on t4.NET_OUID = t3.NET_OUID
    left outer join lineitemexceptions as t5 on t5.assetid = t3.art_asset_id and t5.lineitemid = t1.id
where t4.NET_EnclaveID = 1 and t5.AssetId is null
group by t1.id
) as p2 on p2.Id = p0.Id
) as z0
    inner join lineitems as z1 on z1.id = z0.id
order by z0.id

3 个答案:

答案 0 :(得分:1)

我认为这对于重复部件使用CTE是一个不错的选择。 您将不得不将NET_EnclaveIDAssetId添加到GroupBy,并在查询中使用CTE进行过滤。如下所示:

WITH CTE AS
(
    select 
        t4.NET_EnclaveID,
        t5.AssetId
        t1.id as [Id], 
        SUM(case when t0.compliant = 1 then 1 else 0 end) as [USNNetworkCompliant],
        SUM(case when t0.compliant = 0 then 1 else 0 end) as [USNNetworkNonCompliant],
        CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
            NULL 
        ELSE
            convert(decimal(10,2), SUM(case when t0.compliant = 1 then 1 else 0 end) / 
            cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
        end as [USNPercentageNetworkCompliant],
        CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
            NULL 
        ELSE
            convert(decimal(10,2), SUM(case when t0.compliant = 0 then 1 else 0 end) / 
            cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
        end as [USNPercentageNetworkNonCompliant]
    from lineitemsmap as t0
        inner join lineitems as t1 on t1.id = t0.lineitemid
        inner join art_blob as t2 on t2.art_blob_id = t0.blobid
        inner join art_asset as t3 on t3.art_asset_id = t2.art_asset_id and t3.decommissioned = 0 
        inner join net_ou as t4 on t4.NET_OUID = t3.NET_OUID
        left outer join lineitemexceptions as t5 on t5.assetid = t3.art_asset_id and t5.lineitemid = t1.id
    group by 
        t1.id,
        t4.NET_EnclaveID,
        t5.AssetId
)
select z1.description, z0.* from (
select 
    p0.Id,
    p0.[NetworkCompliant],
    p0.[NetworkNonCompliant],
    p0.[PercentageNetworkCompliant],
    p0.[PercentageNetworkNonCompliant],
    p1.[USNNetworkCompliant],
    p1.[USNNetworkNonCompliant],
    p1.[USNPercentageNetworkCompliant],
    p1.[USNPercentageNetworkNonCompliant],
    p2.[USMCNetworkCompliant],
    p2.[USMCNetworkNonCompliant],
    p2.[USMCPercentageNetworkCompliant], 
    p2.[USMCPercentageNetworkNonCompliant]
from (
  select *
  FROM CTE
  where CTE.AssetId is null
) as p0
left outer join (
  select *
  FROM CTE
  where CTE.NET_EnclaveID = 2 and CTE.AssetId is null  
) as p1 on p1.Id = p0.id
left outer join 
(
  select *
  FROM CTE
  where CTE.NET_EnclaveID = 1 and CTE.AssetId is null
) as p2 on p2.Id = p0.Id
) as z0
    inner join lineitems as z1 on z1.id = z0.id
order by z0.id

答案 1 :(得分:0)

我试图将那个长查询分成几部分。有一个长SELECT重复三次(唯一的区别是重命名的列)。:

SELECT 
    t1.id as [Id], 
    SUM(case when t0.compliant = 1 then 1 else 0 end) as [USMCNetworkCompliant],
    SUM(case when t0.compliant = 0 then 1 else 0 end) as [USMCNetworkNonCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 1 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    END as [USMCPercentageNetworkCompliant],
    CASE WHEN SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) = 0 THEN 
        NULL 
    ELSE
        convert(decimal(10,2), SUM(case when t0.compliant = 0 then 1 else 0 end) / 
        cast(SUM(case when t0.compliant = 0 then 1 else 0 end) + SUM(case when t0.compliant = 1 then 1 else 0 end) as float) * 100)
    END as [USMCPercentageNetworkNonCompliant]
    from lineitemsmap as t0
    inner join lineitems as t1 on t1.id = t0.lineitemid
    inner join art_blob as t2 on t2.art_blob_id = t0.blobid
    inner join art_asset as t3 on t3.art_asset_id = t2.art_asset_id and t3.decommissioned = 0 
    inner join net_ou as t4 on t4.NET_OUID = t3.NET_OUID
    left outer join lineitemexceptions as t5 on t5.assetid = t3.art_asset_id and t5.lineitemid = t1.id

我从现在开始将这个创作命名为YOUR_BIG_SELECT。可能有一些优化可以在这里完成。如果不出意外,那些CASE陈述看起来很丑陋。然后将上面的SELECT放入一个大包装查询 - 我已将p0,p1和p2重命名为networkusnusm以提高可读性。

select z1.description, z0.* from (
    select 
        network.Id,
        network.somecolumns,
        usn.somecolumns,
        usm.somecolumns,
    from (             YOUR_BIG_SELECT where                          t5.AssetId is null group by t1.id) as network
    left outer join (  YOUR_BIG_SELECT where t4.NET_EnclaveID = 2 and t5.AssetId is null group by t1.id) as usn on usn.Id = network.id
    left outer join (  YOUR_BIG_SELECT where t4.NET_EnclaveID = 1 and t5.AssetId is null group by t1.id) as usm on usm.Id = network.Id
) as z0
inner join lineitems as z1 on z1.id = z0.id
order by z0.id

加入lineitems似乎没必要。 network.Id来自lineitems.id(内部联接为YOUR_BIG_SELECT中的t1)。因此,您只需将t1.description添加到YOUR_BIG_SELECT,然后将您的查询改为:

select 
    network.Id,
    network.description
    network.somecolumns,
    usn.somecolumns,
    usm.somecolumns,
    from (             YOUR_BIG_SELECT where                          t5.AssetId is null group by t1.id) as network
    left outer join (  YOUR_BIG_SELECT where t4.NET_EnclaveID = 2 and t5.AssetId is null group by t1.id) as usn on usn.Id = network.id
    left outer join (  YOUR_BIG_SELECT where t4.NET_EnclaveID = 1 and t5.AssetId is null group by t1.id) as usm on usm.Id = network.Id
order by network.id

我会看到摆脱这些子查询的机会,但这个解决方案不会更漂亮,所以我没有看到一点。

这就是我到目前为止所提出的。

答案 2 :(得分:0)

我已修改并希望简化您的要求。您可能需要重命名结果列,但这里有......

是的,您的查询基础几乎相同,但Enclave标志除外。第一个查询获取所有条目作为所有网络合规/不合规总计和百分比的基线。然后,对于USN应用与Enclave flag = 2完全相同的查询,对于USMC应用flag = 1。

所以我所做的是一个简单的查询来获取每一行,并且它的相应标志是“我不关心”(其中没有考虑标志),而Enclave标志分别为1或2。

因此,这给了我在Compliant或NonCompliant中的值为1或0的所有行,以及另外一组标志,以指示它基于Enclave 1或2。

现在,首先,我采用这个PQ(PreQuery)或原始的单独行并根据ID应用聚合,并获得Compliant,NonCompliant和相应的Compliant的总和,或者不用于飞地1和飞地2 ...现在都是汇总到每个ID级别。

现在,我将所有的SUMs()与分类(包围或不包括标志)一起考虑在内。因为我可以说,现在简化了CASE WHEN NetworkCompliant + NetworkNonCompliant = 0然后null else ...

现在,在分区中,而不是强制转换为浮动,如果我只做1.0000 *(等等),我只是强迫浮动到分区的那一部分。

所以,我有3个“值集”值...符合,NonCompliant,%兼容,%不符合ALL,Enclave 1标志(后缀为1)和Enclave 2标志(后缀为2)。

希望这有意义,并会为你而战。与原始查询一样复杂,我确信你会发现我在这个答案中可能遇到的任何“oops”类型o错误,因为我显然没有生产(甚至样本)表格。

select
      PreSum1.ID,

      NetworkCompliant,
      NetworkNonCompliant,
      CASE WHEN PreSum1.NetworkCompliant + PreSum1.NetworkNonCompliant = 0
         THEN null
         ELSE convert( decimal(10,2), 
             ( PreSum1.NetworkCompliant / ( 1.0000 * PreSum1.NetworkCompliant + PreSum1.NetworkNonCompliant ) * 100 )
         END as [PercentageNetworkCompliant],
      CASE WHEN PreSum1.NetworkCompliant + PreSum1.NetworkNonCompliant = 0
         THEN null
         ELSE convert( decimal(10,2), 
             ( PreSum1.NetworkNonCompliant / ( 1.0000 * PreSum1.NetworkCompliant + PreSum1.NetworkNonCompliant ) * 100 )
         END as [PercentageNetworkNonCompliant],

      NetworkCompliant1,
      NetworkNonCompliant1,
      CASE WHEN PreSum1.NetworkCompliant1 + PreSum1.NetworkNonCompliant1 = 0
         THEN null
         ELSE convert( decimal(10,2), 
             ( PreSum1.NetworkCompliant1 / ( 1.0000 * PreSum1.NetworkCompliant1 + PreSum1.NetworkNonCompliant1 ) * 100 )
         END as [USMCPercentageNetworkCompliant1],
      CASE WHEN PreSum1.NetworkCompliant1 + PreSum1.NetworkNonCompliant1 = 0
         THEN null
         ELSE convert( decimal(10,2), 
             ( PreSum1.NetworkNonCompliant1 / ( 1.0000 * PreSum1.NetworkCompliant1 + PreSum1.NetworkNonCompliant1 ) * 100 )
         END as [USMCPercentageNetworkNonCompliant1],

      NetworkCompliant2,
      NetworkNonCompliant2,
      CASE WHEN PreSum1.NetworkCompliant2 + PreSum1.NetworkNonCompliant2 = 0
         THEN null
         ELSE convert( decimal(10,2), 
             ( PreSum1.NetworkCompliant2 / ( 1.0000 * PreSum1.NetworkCompliant2 + PreSum1.NetworkNonCompliant2 ) * 100 )
         END as [USNPercentageNetworkCompliant2],
      CASE WHEN PreSum1.NetworkCompliant2 + PreSum1.NetworkNonCompliant2 = 0
         THEN null
         ELSE convert( decimal(10,2), 
             ( PreSum1.NetworkNonCompliant2 / ( 1.0000 * PreSum1.NetworkCompliant2 + PreSum1.NetworkNonCompliant2 ) * 100 )
         END as [USNPercentageNetworkNonCompliant2]
   from
      ( SELECT
              PQ1.ID,
              SUM( NetworkCompliant ) NetworkCompliant,
              SUM( NetworkNonCompliant ) NetworkNonCompliant
              SUM( NetworkCompliant * EnclaveFlag1 ) NetworkCompliant1,
              SUM( NetworkNonCompliant * EnclaveFlag1 ) NetworkNonCompliant1,
              SUM( NetworkCompliant * EnclaveFlag2 ) NetworkCompliant2,
              SUM( NetworkNonCompliant * EnclaveFlag2 ) NetworkNonCompliant2
           from
              ( select 
                      t0.lineitemid as [Id], 
                      case when t0.compliant = 1 then 1 else 0 end as NetworkCompliant,
                      case when t0.compliant = 0 then 1 else 0 end as NetworkNonCompliant,
                      CASE when t4.NET_EnclaveID = 2 then 1 else 0 end as EnclaveFlag1,
                      CASE when t4.NET_EnclaveID = 2 then 1 else 0 end as EnclaveFlag2
                   from 
                      lineitemsmap as t0
                         inner join lineitems as t1 
                            on t0.lineitemid = t1.id 
                            inner join art_blob as t2 
                              on t0.blobid = t2.art_blob_id
                              inner join art_asset as t3 
                                 on t2.art_asset_id  = t3.art_asset_id
                                 and t3.decommissioned = 0    
                                 inner join net_ou as t4 
                                    on t3.NET_OUID = t4.NET_OUID
                                    left outer join lineitemexceptions as t5 
                                       on t1.id = t5.lineitemid
                                       and t3.art_asset_id = t5.assetid 
                   where 
                      t5.AssetId is null
                   group by 
                      t0.lineitemid ) as PQ1
           group by
              PQ1.ID ) as PreSum1