sql >> データベース >  >> RDS >> PostgreSQL

多くの内部選択を含む選択クエリを簡素化し、PostgreSQLのパフォーマンスを向上させる方法

    最適化

    1. すべての集計計算を1回の選択で取得-クエリごとにグループ化します。
    2. 副選択を左結合に置き換えます
    3. 外部条件に基づく内部クエリの追加制限。

    これをそのように入手してください:

    with gtab4_5 as (
        select 
            gtab04.Productid, gtab05.BatchId
        FROM
           gtab04 
        LEFT JOIN gtab05 
            ON gtab04.Productid = gtab05.Productid  
        WHERE (gtab04.Masked = False AND gtab04.Banned = false)  
            AND  gtab04.patentid in  (321, 313 , 267 , 431) 
    )
      SELECT 
       gtab04.Productid,
       gtab04.Product,
       gtab04.SaleUnit ,
       gtab04.Packing,
       gtab04.ConvFact,
       gtab04.PTR,
       gtab04.MRP, 
       gtab04.PRate,
       gtab04.PTR1,
       gtab04.PTR2,
       gtab04.Location,
       0 As ManufId,
       gtab07.PatentId,
       gtab07.Patent,
       gtab07.PatentCd,
       gtab15.TaxId,
       gtab15.TaxName, 
       gtab15.TaxType,
       gtab15.TaxRate, 
       gtab15.TxOMRP,
       ''::text As Manufacture,
       stats_ags.StkEntered AS StkEntered,
       stats_ags.OpeningInQty as OpeningInQty,
       stats_ags.OpeningOutQty as OpeningOutQty,
       0 AS PurchQty, 
       0 AS SRetQty, 
       0 AS PerInQty, 
       0 AS SaleQty, 
       0 AS StockInQty,
       0 AS StockOutQty, 
       0 AS SaleAmt, 
       0 AS DamageQty, 
       0 AS PRetQty, 
       0 AS PerOutQty,
       stats_ags.PrMthSaleQty as PrMthSaleQty,
       stats_ags.PrMthSaleAmt as PrMthSaleAmt,
       gtab04.LandCost,
       gtab05.PTR AS BatchPTR,
          (case when (
          gtab05.Fqty -  gtab05.FIQty)>0 then (gtab05.Fqty -  gtab05.FIQty) else 0 end) as 
       IssdFreeQty, 
       gtab05.MRP AS BatchMRP, 
       gtab05.PRate AS BatchPRate, 
       gtab04.StdPack,  
          (date_part('day',  (Select Min(Expiry) From gtab05 WHERE  gtab05.Productid =    
          gtab04.Productid And gtab05.Qty > gtab05.IQty)-Cast('2014-06-20' AS    
          timestamp))) AS 
       ExpDys, 
       stats_ags.LastSaleDate as LastSaleDate ,
       GTAB05.BatchId, 
       0 AS FreeSaleQty, 
       0 AS ReplSaleQty 
    FROM
       gtab04 
    INNER JOIN  gtab15 
        ON gtab04.TaxId = gtab15.TaxId  
    LEFT JOIN gtab05 
        ON gtab04.Productid = gtab05.Productid   
    INNER JOIN gtab07 
        ON gtab07.Patentid = gtab04.Patentid  
    left join (
            SELECT gtab10_9.Productid, gtab10_9.BatchId, 
                max( case 
                    when gtab10_9.acyrid = 7 
                    then gtab10_9.Productid else null 
                end) as StkEntered,
                SUM( case 
                    when gtab10_9.acyrid = 7 and ( 
                        gtab10_9.vrid = 6 
                    or (
                        gtab10_9.vrid in (10,11,23,42,35) 
                        AND gtab10_9.trdate < Cast('2014-06-01' AS timestamp) 
                    ) ) 
                    then gtab10_9.qty else 0 
                end) as OpeningInQty,
                SUM( case 
                    when gtab10_9.acyrid = 7 
                        and gtab10_9.vrid in( 12,32,33,44 ,45 ,46, 47 ,48 , 49,18 , 34 ,25,27 ,15,26,24 , 43 ,36) 
                        AND gtab10_9.trdate < Cast('2014-06-01'   AS timestamp)                 
                    then gtab10_9.qty else 0 
                end) as OpeningOutQty,
                SUM( case 
                    when gtab10_9.acyrid = 7 
                        and gtab10_9.vrid in(12 ,32 ,33 ,44 ,45 ,46 ,47,48,49) 
                        AND gtab10_9.trdate BETWEEN '2014-05-01' AND '2014-05-31'               
                    then gtab10_9.qty else 0 
                end) as PrMthSaleQty,
                SUM( case 
                    when gtab10_9.acyrid = 7 
                        and gtab10_9.vrid in( 12, 32 , 33 , 44 ,45 ,46 , 47,48 , 49) 
                        and (gtab10_9.FreeOrRpl = 0 OR gtab10_9.FreeOrRpl = 2) 
                        AND gtab10_9.trdate BETWEEN '2014-05-01' AND '2014-05-31'               
                    then gtab10_9.qty * gtab10_9.ptr else 0 
                end) as PrMthSaleAmt,
                MAX( case 
                    when gtab10_9.acyrid = 7 
                        and gtab10_9.VrId in (12,32,33,44,45,46, 47,48,49)
                        and (gtab10_9.FreeOrRpl = 0 OR gtab10_9.FreeOrRpl = 2) 
                    then gtab10_9.TrDate else null 
                end) as LastSaleDate
            FROM (
                SELECT gtab10.*, gtab09.*
                FROM gtab10 
                INNER JOIN gtab09 ON gtab09.TranId = gtab10.TranId 
                inner join gtab4_5 on   gtab4_5.Productid = gtab10.Productid and gtab4_5.BatchId = gtab10.BatchId
            ) gtab10_9 
            group by gtab10_9.Productid, gtab10_9.BatchId
        ) stats_ags
        on stats_ags.Productid = gtab04.Productid 
        and stats_ags.BatchId = gtab05.BatchId
    WHERE (gtab04.Masked = False AND gtab04.Banned = false)  
        AND  gtab04.patentid in  (321, 313 , 267 , 431) 
    ORDER BY Patent, gtab04.Product
    

    このクエリでの私の結果:

    Sort  (cost=82928.96..82931.84 rows=1152 width=306) (actual time=447.433..450.191 rows=2421 loops=1)
      Sort Key: gtab07.patent, gtab04.product
      Sort Method: external merge  Disk: 680kB
    

    対元のバリアント:

    Sort  (cost=2796544.62..2796547.50 rows=1152 width=278) (actual time=47865.883..47868.570 rows=2421 loops=1)
      Sort Key: gtab07.patent, gtab04.product
      Sort Method: external merge  Disk: 680kB
    

    並べ替えのサイズと行数は、想定されているものと同じです...

    サンプルデータに基づく測定PG9.3



    1. Laravel 4:EloquentクラスのすべてのクエリにWHERE条件を適用するにはどうすればよいですか?

    2. Oracle10gリリース2で制御ファイルを編集します

    3. mysqlgroupbyおよび左結合で2番目に高い値を取得する方法

    4. postgresqlクエリで文字列のリスト内の列挙型を検索するにはどうすればよいですか?