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

标签 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

结果:
特许经营集团;店铺编号;店名;商店代码;开始;组织ID

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

  2. "FARMER";763;"Joe Murphy 的农场";"23355";"1980-04-24";1579

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

  4. "CDJRF";623;"克拉格斯";"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

结果:
商店数量;店铺编号;店名;商店代码;开始;组织ID;品牌集团

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

  2. 2;763;"克拉格斯";"23355";"1980-04-24";1579;"CDJR"

  3. 1;763;"克拉格斯";"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'

结果:
商店数量;店铺编号;店名;商店代码;开始;组织ID;品牌集团

  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;"克拉格斯";"23355";"1980-04-24";1579;"菲亚特"

最后一个 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. 您的查询格式正确且可读。

  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;

关于sql - 在 PostgreSQL 中编写此查询的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50936155/

相关文章:

sql - 根据另外两个表的计数创建一个指标表

ruby-on-rails - 使用具有不同属性的相似模型的 Rails 数据库设计

java - 一个批处理中的两个不同的准备好的语句

mysql - 使用以相同字段开头的 GROUP BY 优化多个查询

SQL 中的 LIKE 下划线

c# - 如何在 Npgsql.EntityFrameworkCore 中查询具有 JSON 数组的列

sql - postgresql:\copy 方法输入有效条目并丢弃异常

sql - PostgreSQL:从 5 分钟前的表中获取行

c# - 使用sql server express为c#.net winform应用程序创建多个用户

mysql - 不同表上的简单触发器更新