在PostgreSQL中编写此查询的更好方法

时间:2018-06-19 20:05:51

标签: sql postgresql

我创建了以下查询,从本质上将商店合并为特定的组。这些组是CDJR,CDJRF,ANP和FARMER。这是我想到的最有效的查询方法。您知道更快,更少代码驱动的查询吗?我正在学习如何成为一个更高效的查询编写器,任何输入将不胜感激。请阅读查询下方的详细信息。请注意,为简单起见,我仅添加了4个商店代码。让我知道是否需要更多信息。

WITH CTE
AS
(
    SELECT 
        COUNT(D.storecode) AS StoreCount,
        D.storeid,
        D.storename,                    
        D.storecode,                    
        D.start,                    
        D.organizationid,
        CASE
            WHEN F.storefranchisetypeid IN (1, 2, 3, 4, 7, 25, 19, 20, 26, 29, 30) THEN 'CDJR'
            WHEN F.storefranchisetypeid IN (21, 23, 28) THEN 'FARMER' 
            WHEN F.storefranchisetypeid = 22 THEN 'ANP' 
        END AS BrandGroup
    FROM 
        store AS D                                              
        JOIN organization AS BO     ON D.organizationid = BO.organizationid
        JOIN franchises AS F        ON D.storeid= F.storeid
        JOIN franchisetype AS FT    ON F.franchisetypeid = FT.franchisetypeid   
    WHERE
        BO.countryid = 6            -- USA only.
        AND D.end IS NULL           -- Active stores.
        AND FT.active IS TRUE       
        AND F.end IS NULL           -- Active franchises.
        AND D.franchised = 'F'
        AND D.trainingtypeid = 1
        AND D.storemarket = 'M'
        AND D.storecodes IN (45660, 45733, 54816, 60739)
    GROUP BY
        D.storeid,
        D.storename,                    -- Dealer name detailed.
        D.storecode,                    -- Dealer code.
        D.start,
        D.organizationid,
        CASE
            WHEN F.storefranchisetypeid IN (1, 2, 3, 4, 7, 25, 19, 20, 26, 29, 30) THEN 'CDJR'
            WHEN F.storefranchisetypeid IN (21, 23, 28) THEN 'FARMER' 
            WHEN F.storefranchisetypeid = 22 THEN 'ANP' 
        END
),
CTE2
AS
(
    SELECT *
    FROM
        CTE
    EXCEPT
    SELECT *
    FROM
        CTE
    WHERE
        storecount <= 4
        AND brandgroup = 'CDJR'
),
CTE3
AS
(
    SELECT
        'CDJRF' AS FranchiseGroup,
        storeid,
        storename,
        storecode,
        start,
        organizationid
    FROM
        CTE2
    GROUP BY
        storeid,
        storename,
        storecode,
        start,
        organizationid
    HAVING
        COUNT(storecode) >= 2
    UNION
    SELECT
        BrandGroup,
        storeid,
        storename,
        storecode,
        start,
        organizationid
    FROM
        CTE2
    WHERE
        storecode NOT IN
            (
                SELECT
                    storecode
                FROM
                    CTE2
                GROUP BY
                    storecode
                HAVING
                    COUNT(storecode) >= 2
            )
)
SELECT *
FROM CTE3

结果:
特许集团StoreID; StoreName; StoreCode;开始; OrganizationID

  1. “ CDJR”; 520;“帕克市场”;“ 05002”;“ 1954-11-24”; 1336

  2. “农民”; 763;“乔·墨菲的农场”;“ 23355”;“ 1980-04-24”; 1579

  3. “ ANP”; 80549;“ A&P”;“ 69069”;“ 2011-04-25”; 283224

  4. “ CDJRF”; 623;“ Kraggers”;“ 09733”;“ 1952-01-24”; 1439

在下面的第一个CTE中,我提取存储数据,对其进行计数,然后将类型ID最初分为3组,而不是分为4组。CTE的结果在CTE查询下方提供。

SELECT 
            COUNT(D.storecode) AS StoreCount,
            D.storeid,
            D.storename,                    
            D.storecode,                    
            D.start,                    
            D.organizationid,
            CASE
                WHEN F.storefranchisetypeid IN (1, 2, 3, 4, 7, 25, 19, 20, 26, 29, 30) THEN 'CDJR'
                WHEN F.storefranchisetypeid IN (21, 23, 28) THEN 'FARMER' 
                WHEN F.storefranchisetypeid = 22 THEN 'ANP' 
            END AS BrandGroup
        FROM 
            store AS D                                              
            JOIN organization AS BO     ON D.organizationid = BO.organizationid
            JOIN franchises AS F        ON D.storeid= F.storeid
            JOIN franchisetype AS FT    ON F.franchisetypeid = FT.franchisetypeid   
        WHERE
            BO.countryid = 6            -- USA only.
            AND D.end IS NULL           -- Active stores.
            AND FT.active IS TRUE       
            AND F.end IS NULL           -- Active franchises.
            AND D.franchised = 'F'
            AND D.trainingtypeid = 1
            AND D.storemarket = 'M'
            AND D.storecodes IN (45660, 45733, 54816, 60739)
        GROUP BY
            D.storeid,
            D.storename,                    -- Dealer name detailed.
            D.storecode,                    -- Dealer code.
            D.start,
            D.organizationid,
            CASE
                WHEN F.storefranchisetypeid IN (1, 2, 3, 4, 7, 25, 19, 20, 26, 29, 30) THEN 'CDJR'
                WHEN F.storefranchisetypeid IN (21, 23, 28) THEN 'FARMER' 
                WHEN F.storefranchisetypeid = 22 THEN 'ANP' 
            END

结果:
StoreCount; StoreID; StoreName; StoreCode;开始; OrganizationID;品牌集团

  1. 1; 80549;“ A&P”;“ 69069”;“ 2011-04-25”; 283224;“ ANP”

  2. 2; 763;“ Kraggers”;“ 23355”;“ 1980-04-24”; 1579;“ CDJR”

  3. 1; 763;“ Kraggers”;“ 23355”;“ 1980-04-24”; 1579;“农民”

  4. 7; 623;“乔·墨菲的农场”;“ 09733”;“ 1952-01-24”; 1439;“ CDJR”

  5. 1; 623;“乔·墨菲的农场”;“ 09733”;“ 1952-01-24”; 1439;“农民”

  6. 6; 520;“帕克农场”;“ 05002”;“ 1954-11-24”; 1336;“ CDJR”

第二个CTE CTE2删除了不相关的CDRJ。结果在查询下方。

CTE2
AS
(
    SELECT *
    FROM
        CTE
    EXCEPT
    SELECT *
    FROM
        CTE
    WHERE
        storecount <= 4
        AND brandgroup = 'CDJR'

结果:
StoreCount; StoreID; StoreName; StoreCode;开始; OrganizationID;品牌集团

  1. 6; 520;“帕克农场”;“ 05002”;“ 1954-11-24”; 1336;“ CDJR”

  2. 1; 80549;“ A&P”;“ 69069”;“ 2011-04- 25”; 283224;“ ANP”

  3. 1; 623;“乔·墨菲的农场”;“ 09733”;“ 1952-01-24”; 1439;“菲亚特”

  4. 7; 623;“乔·墨菲的农场”;“ 09733”;“ 1952-01-24”; 1439;“ CDJR”

  5. 1; 763;“ Kraggers”;“ 23355”;“ 1980-04-24”; 1579;“ FIAT”

最后一个CTE CTE3在我计算出CDRJF结果与其他组后将其结合在一起。所有结果都将导致页面顶部的第一组结果。

SELECT
    'CDJRF' AS FranchiseGroup,
    storeid,
    storename,
    storecode,
    start,
    organizationid
FROM
    CTE2
GROUP BY
    storeid,
    storename,
    storecode,
    start,
    organizationid
HAVING
    COUNT(storecode) >= 2
UNION
SELECT
    BrandGroup,
    storeid,
    storename,
    storecode,
    start,
    organizationid
FROM
    CTE2
WHERE
    storecode NOT IN
        (
            SELECT
                storecode
            FROM
                CTE2
            GROUP BY
                storecode
            HAVING
                COUNT(storecode) >= 2
        )

1 个答案:

答案 0 :(得分:1)

  1. 您的查询格式正确且可读性强。

  2. 您意识到它效率不高。

不好

  1. 样本数据格式不正确且易于使用。

主要问题在于简化逻辑。这未经测试(请参阅坏点#1),但可能会让您了解如何清除它。

SELECT DISTINCT *
  FROM ( SELECT CASE WHEN COUNT(storeCode) OVER 
                            ( PARTITION BY  storeid,
                                            storename,
                                            storecode,
                                            start,
                                            organizationid

                            ) >= 2 THEN 'CDJRF'
                     ELSE BandGroup
                 END,
                storeid,
                storename,
                storecode,
                start,
                organizationid
           FROM (
                SELECT 
                    COUNT(D.storecode) AS StoreCount,
                    D.storeid,
                    D.storename,                    
                    D.storecode,                    
                    D.start,                    
                    D.organizationid,
                    F.BrandGroup
                FROM 
                    store AS D                                              
                    JOIN organization AS BO     ON D.organizationid = BO.organizationid
                    JOIN (SELECT store_id,
                                 CASE
                                      WHEN F.storefranchisetypeid IN (1, 2, 3, 4, 7, 25, 19, 20, 26, 29, 30) THEN 'CDJR'
                                      WHEN F.storefranchisetypeid IN (21, 23, 28) THEN 'FARMER' 
                                      WHEN F.storefranchisetypeid = 22 THEN 'ANP' 
                                  END AS BrandGroup,
                                 end
                            FROM franchises
                         ) F
                      ON D.storeid= F.storeid
                    JOIN franchisetype AS FT    ON F.franchisetypeid = FT.franchisetypeid   
                WHERE
                    BO.countryid = 6            -- USA only.
                    AND D.end IS NULL           -- Active stores.
                    AND FT.active IS TRUE       
                    AND F.end IS NULL           -- Active franchises.
                    AND D.franchised = 'F'
                    AND D.trainingtypeid = 1
                    AND D.storemarket = 'M'
                    AND D.storecodes IN (45660, 45733, 54816, 60739)
                GROUP BY
                    D.storeid,
                    D.storename,                    -- Dealer name detailed.
                    D.storecode,                    -- Dealer code.
                    D.start,
                    D.organizationid,
                    F.BrandGroup
                ) CTE
         WHERE storeCount > 4
            OR bandGroup <> 'CDJR'
    ) SUB;