【问题标题】:Need some help for a Query Optimization查询优化需要一些帮助
【发布时间】:2019-06-02 18:35:45
【问题描述】:

我有以下查询,但渲染结果似乎需要超过一分钟。谁能帮我优化结果?我相信下面的第二个查询会对第一行有所帮助,但不确定如何分组

SELECT
  (SELECT COUNT(delivery_id)
   FROM DeliveryTons
   WHERE EXISTS
       (SELECT BSI_CODE
        FROM FarmerGroups
        WHERE ASSN = 'BSICGP'
          AND BSI_CODE = DeliveryTons.farmer_pay_bsi
          AND remarks = ''
          AND DeliveryTons.crop_season = 3)) AS Tickets,

  (SELECT COUNT(delivery_id)
   FROM DeliveryTons
   WHERE EXISTS
       (SELECT BSI_CODE
        FROM FarmerGroups
        WHERE ASSN = 'BSICGP'
          AND BSI_CODE = DeliveryTons.farmer_pay_bsi
          AND DeliveryTons.crop_season = 3)) AS Deliveries,

  (SELECT SUM(tonnage_adjusted)
   FROM DeliveryTons
   WHERE EXISTS
       (SELECT BSI_CODE
        FROM FarmerGroups
        WHERE ASSN = 'BSICGP'
          AND BSI_CODE = DeliveryTons.farmer_pay_bsi
          AND delivery_status != 'C'
          AND DeliveryTons.crop_season = 3)) AS TonsDelivered,

  (SELECT SUM(tonnage_adjusted)
   FROM DeliveryTons
   WHERE EXISTS
       (SELECT BSI_CODE
        FROM FarmerGroups
        WHERE ASSN = 'BSICGP'
          AND BSI_CODE = DeliveryTons.farmer_pay_bsi
          AND remarks = ''
          AND DeliveryTons.crop_season = 3)) AS TonsMonitored,

  (SELECT SUM(ACREAGE)
   FROM CaneParcel
   WHERE EXISTS
       (SELECT DISTINCT(parcel_id)
        FROM DeliveryTons
        WHERE EXISTS
            (SELECT BSI_CODE
             FROM FarmerGroups
             WHERE ASSN = 'BSICGP'
               AND BSI_CODE = DeliveryTons.farmer_pay_bsi
               AND CaneParcel.FIELD_ID = DeliveryTons.parcel_id
               AND DeliveryTons.crop_season = 3))) AS AcresMonitored,

  (SELECT SUM(ACREAGE)
   FROM CaneParcel
   WHERE EXISTS
       (SELECT DISTINCT(parcel_id)
        FROM DeliveryTons
        WHERE EXISTS
            (SELECT BSI_CODE
             FROM FarmerGroups
             WHERE ASSN = 'BSICGP'
               AND BSI_CODE = DeliveryTons.farmer_pay_bsi
               AND remarks = ''
               AND CaneParcel.FIELD_ID = DeliveryTons.parcel_id
               AND parcel_status = '3'
               AND DeliveryTons.crop_season = 3))) AS ClosedAcres



SELECT COUNT(d.delivery_id),
FROM DeliveryTons d
INNER JOIN FarmerGroups F ON F.BSI_CODE = d.farmer_pay_bsi
WHERE t.assn = 'BSICGP'
  AND crop_season = 3
  AND remarks=''
GROUP BY d.delivery_id

这是我的 DeliveryTons 表:

id      crop_season  delivery_id  parcel_id    reaping_code   farmer_owner_name   farmer_owner_bsi   farmer_pay_bsi   tonnage_adjusted   parcel_status   remarks    delivery_status
77701   1             1           038 - 0358   CGP001         Not defined         0                   2064            15.3625            2                          P
77702   1             2           038 - 0358   CGP001         Not defined         0                   2064            17.4625            2                          P
77703   1             3           038 - 0358   CGP001         Not defined         0                   2064            13.5875            2                          P
77704   1             4           038 - 0358   CGP001         Not defined         0                   2064            19.0250            2                          P
77705   1             5           038 - 0358   CGP001         Not defined         0                   2064            19.6375            2                          P
77706   1             6           038 - 0358   CGP001         Not defined         0                   2064            16.2125            2                          P
77707   1             7           038 - 0358   CGP001         Not defined         0                   2064            22.5375            2                          P
77708   1             8           038 - 0358   CGP001         Not defined         0                   2064            18.1000            2                          P
77709   1             9           038 - 0358   CGP001         Not defined         0                   2064            23.0000            2                          P
77710   1            11           016 - 0482   BSFA156        CANUL, MARTIN       844                 7866            19.3000            1                          P
77711   1            12           016 - 0096   BSFA153        ALDANA, MARCOS      986                10024            15.2625            1                          P
77712   1            13           004 - 0684   BSFA155        QUEME, BENANCIO     778                10063            17.8125            1                          P
77713   1            14           004 - 0224   BSFA162        CHABLE, MARCELINO   198                  198            20.5125            1                          P
77714   1            15                        BSFA160                            0                    212            16.0375            0               NO_TICKET  P
77715   1            16                        BSFA159                            0                   4570            12.3875            0               NO_TICKET  P
77716   1            17           016 - 2473   BSFA151                            0                   9173            13.6875            3                          P
77717   1            18           016 - 1566   BSFA149        Not defined         0                   1094            15.7250            1                          P
77718   1            19                        BSFA160                            0                    148            20.2125            0               NO_TICKET  P
77719   1            20           016 - 1566   BSFA149        Not defined         0                   1094            12.7625            2                          P
77720   1            21           016 - 1566   BSFA149        Not defined         0                   1094            15.3875            2                          P
77721   1            22           016 - 2152   BSFA175                            0                    926            15.2625            3                          P
77722   1            23                        BSFA175                            0                   5498            13.7250            0               NO_TICKET  P

甘蔗包裹表:

geoid   FIELD_ID      BSI_CODE   ACREAGE     ASSN
0       004 - 0567    47          7.359515   CSCPA
1       004 - 0008    281        12.38654    CSCPA
2       004 - 0012    281         7.899037   CSCPA
3       004 - 0013    281         4.937749   CSCPA
4       004 - 0014    281         5.002847   CSCPA
5       004 - 0038    9050        6.731369   CSCPA
6       004 - 0045    9028        4.120158   CSCPA
7       004 - 0039    9050        8.519387   CSCPA
8       004 - 0147    289        14.801      BSCFA - CZ
9       004 - 0572    47          5.878942   CSCPA
10      004 - 0030    281        14.33925    CSCPA
11      004 - 1150    281         7.306061   CSCPA
12      004 - 1152    281         3.814288   CSCPA
13      004 - 0017    281        11.5479     CSCPA

FarmerGroups 表:

ID      ASSN          BSI_CODE FARMER                       CROP_SEASON
10473   BSCFA - OW    5752       GARCIA,EUGENIO R           2
10474   BSCFA - OW    8894       GARCIA,RAUL R              2
10475   BSCFA - OW    4427       PECH,EVELIA                2
10476   BSCFA - OW    5226       GONZALEZ,DALIA MARIA       2
10477   BSCFA - OW    5753       GONZALEZ,ELVIRA            2
10478   BSCFA - OW    9295       GONZALEZ,RAUL              2
10479   BSCFA - OW    9996       GONZALEZ,TRANSITO          2
10480   BSCFA - OW    10099      PERAZA,ALBERTA             2
10481   BSCFA - OW    4537       GARCIA,SANTIAGO SILVERIO   2
10482   BSCFA - OW    8573       ACK,AMELITA M              2
10483   BSCFA - OW    7467       ACK,EUCARIO                2
10484   BSCFA - OW    7468       ACK,MOISES                 2
10485   BSCFA - OW    1848       AGUIRRE,NENCIE             2
10486   BSCFA - OW    4355       BLANCO,SILVIO              2
10487   BSCFA - OW    4476       CAL,ALBERTA GARCIA         2
10488   BSCFA - OW    4480       CAL,ENRIQUE                2
10489   BSCFA - OW    2545       CAL,ERNESTO T              2
10490   BSCFA - OW    6877       CAL,REMIGIO                2

【问题讨论】:

  • 这是什么数据库?甲骨文? SQL 服务器? DB2?火力基地? MySQL 版本 8? V8之前的MySQL? 这些事情真的很重要!请在选择正确的 dbms 标记时提及版本。
  • 计数d.delivery_id 然后GROUP BY d.delivery_id 真的没有多大意义。 您是否希望结果中只有一行?
  • 如果你只想要一行,那么就不要group by
  • 为了进一步帮助真正需要样本数据(每个表格而不是图像)。我建议您阅读以下内容:Provide a Minimal Complete Verifiable Example (MCVE)Why should I provide a MCVE
  • 该评论没有意义,如果您不删除该组,您会得到 60?如果这是真的,我建议您需要改用 count (distinct ...) 并删除该组。

标签: sql sql-server-2008 optimization query-optimization


【解决方案1】:

如果 FarmerGroups 可以为单个 BSI_CODE 记录创建多行,则每个 BSI_CODE 预聚合农民组表 ONCE 的标志。那么你可以在不产生错误的笛卡尔结果的情况下对其求和......

将内部的“PQ”(PreQuery)想象成在行之间进行二元或运算。您只关心任何单个 BSI_CODE,它是否存在,是否有空状态(或没有),以及它的交付状态。所以,给定样本数据...

FarmerGroups
BSI_CODE   Assn     Remarks   Delivery_Status
A          BSICGP   test      B
A          BSICGP             C
A          BSICGP   test      C
A          BSICGP             A
---------------------------------
B          BSICGP   test      B
B          BSICGP   test      C
---------------------------------
C          BSICGP   test      B
---------------------------------
D          BSICGP             
D          BSICGP             X
---------------------------------
E          BSICGP   test1     C
E          BSICGP   test2     C
---------------------------------

现在,每个 BSI_CODE 的摘要结果为

BSI_CODE   NoRemarks  IsTonDelivery
A          1          1    (at least 1 record had no remarks, at least 1 record was NOT 'C' status)
B          0          1    (NO records had empty remarks, at least 1 was NOT 'C' status)
C          0          1    (only 1 record.  It had a remark, but as NOT 'C' status)
D          1          1    (both no remarks, neither was 'C' status)
E          0          0    (both HAD remarks and BOTH were 'C' status).

因此您可以看到农民组的 11 条记录汇总为 5 行,其中“标志”列分别为 1 或 0。

对于您的“CaneParcel”,采用一种有点类似的方法,根据字段 ID 对面积进行预求和,这样每个字段也有一行,左连接到交货吨...... FarmerGroups 将通过传递条件对该部分进行资格预审。

现在,如果您的 DeliveryTons 表有 5 条记录为“D”,则求和、计数或乘以标志将导致 0 或尝试获取总和的值。您可以加入您的 DeliveryTons 表,并且由于您的每个子查询都依赖于 Crop_Season = 3,您可以将其应用于您的外部查询,但将上述查询拉入...

select
        count(*) as Deliveries,
        sum( case when dt.remarks = '' then 1 else 0 end ) as Tickets,
        sum( dt.Tonnage_Adjusted 
            * case when dt.delivery_status != 'C' then 1 else 0 end  ) as TonsDelivered,
        sum( dt.Tonnage_Adjusted 
            * case when dt.remarks = '' then 1 else 0 end ) as TonsMonitored,
        sum( PQ2.totalAcreage ) AcresMonitored,
        sum( case when dt.parcel_status = '3' then cp.Acreage else 0 end
            * case when dt.remarks = '' then 1 else 0 end ) TotalClosedAcres
    from
        DeliveryTons dt
            JOIN
            (SELECT DISTINCT
                    BSI_CODE,
                FROM 
                    FarmerGroups fg
                WHERE
                    ASSN = 'BSICGP' ) PQ
                ON dt.farmer_pay_bsi = PQ.BSI_CODE

            LEFT JOIN
            (select
                    cp.Field_ID,
                    sum( cp.Acreage ) totalAcreage
                from
                    CaneParcel cp
                group by
                    cp.Field_ID ) PQ2
                on dt.parcel_id = PQ2.Field_ID

    where
        dt.Crop_Season = 3

这可能需要消化很多,但请相信(无需查看您的实际生产数据 - 甚至是样本数据)作为两个快速预查询聚合(PQ 和 PQ2)一次并直接加入(左加入)到 DeliveryTons 表。我会分块尝试,只是为了看看/确认发生了什么。

每条评论更新

更新了查询。如果没有您的示例数据,我的查询是用隐含的格式/内容编写的。查看您的数据后,请注意 cmets 的 farmerGroups 表中没有任何值,并且它在您的吨位表中。调整查询以适应。

【讨论】:

  • 我收到以下错误:消息 207,级别 16,状态 1,第 13 行无效的列名“备注”。消息 207,级别 16,状态 1,第 14 行无效的列名称“delivery_status”。消息 207,级别 16,状态 1,第 27 行无效的列名称“parcel_status”。
  • 我还上传了示例数据和表格。
  • 我会得到这些错误的任何原因。 - 消息 207,级别 16,状态 1,第 13 行无效的列名“备注”。消息 207,级别 16,状态 1,第 14 行无效的列名称“delivery_status”。消息 4104,级别 16,状态 1,第 27 行无法绑定多部分标识符“dt.parcel_status”。
  • @ivias,请参阅底部的修订和评论。
  • 好的,我看到你已经修改了,但是当我尝试执行查询时仍然出现这些错误。消息 207,级别 16,状态 1,第 16 行无效的列名“delivery_status”。消息 207,级别 16,状态 1,第 29 行无效的列名称“parcel_status”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 2012-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多