Search code examples
postgresqlcrosstabpostgres-crosstab

Duplicate Category Name Error 42710 in Crosstab query Postgres


I am having a tough time getting my crosstab query to execute. I keep getting "Duplicate Category Name Error 42710" when I run the following query.

SELECT
    *
FROM
    crosstab (
        $$
        Select
            date_year,
            city_size,
            sum(Total_Rev)
        From
            (
                SELECT
                    EXTRACT(YEAR FROM SOLD.DATE) Date_Year,
                    CASE WHEN CITY.POPULATION < 3700000 THEN 'SMALL' WHEN CITY.POPULATION >= 3700000
                    AND CITY.POPULATION < 6700000 THEN 'MEDIUM' WHEN CITY.POPULATION >= 6700000
                    AND CITY.POPULATION < 9000000 THEN 'LARGE' WHEN CITY.POPULATION >= 9000000 THEN 'X_LARGE' END City_Size,
                    CASE WHEN DISCOUNT_ON.DISCOUNT_PERCENTAGE IS NOT NULL THEN (
                        (DISCOUNT_ON.DISCOUNT_PERCENTAGE / 100) * PRODUCT.RETAIL_PRICE
                    ) * SOLD.QUANTITY WHEN DISCOUNT_ON.DISCOUNT_PERCENTAGE IS NULL THEN PRODUCT.RETAIL_PRICE * SOLD.QUANTITY END Total_Rev
                FROM
                    SOLD,
                    STORE,
                    CITY,
                    DISCOUNT_ON,
                    PRODUCT
                WHERE
                    CITY.CITY_NAME = STORE.CITY_NAME
                    AND SOLD.PID = PRODUCT.PID
                    AND SOLD.PID = DISCOUNT_ON.PID
                    AND SOLD.DATE = DISCOUNT_ON.DATE
                    AND STORE.STORE_NUMBER = SOLD.STORE_NUMBER
            ) tbl1
        group by
            date_year,city_size
        order by
            date_year,city_size $$,
            $$
        SELECT
            CASE WHEN CITY.POPULATION < 3700000 THEN 'SMALL' WHEN CITY.POPULATION >= 6700000
            AND CITY.POPULATION < 9000000 THEN 'LARGE' END City_Size
        FROM
            CITY $$
    ) AS FINAL_RESULT(date_year Numeric,"SMALL" REAL,"MEDIUM" REAL,"LARGE" REAL,"X_LARGE" REAL );

When I run the subquery I do get results:

[Image of Results from Subquery]1

Thank You


Solution

  • Using filtered aggregation is typically easier to deal with than using the crosstab() function:

    select date_year,
           sum(Total_Rev) filter (where city_size = 'SMALL') as small,
           sum(Total_Rev) filter (where city_size = 'MEDIUM') as medium,
           sum(Total_Rev) filter (where city_size = 'LARGE') as large,
           sum(Total_Rev) filter (where city_size = 'X_LARGE') as x_large
    from (
      SELECT EXTRACT(YEAR FROM SOLD.DATE) Date_Year,
             CASE 
               WHEN city.population < 3700000 THEN 'SMALL' 
               WHEN city.population >= 3700000 AND city.population < 6700000 then 'MEDIUM' 
               WHEN city.population >= 6700000 AND city.population < 9000000 then 'LARGE' 
               WHEN city.population >= 9000000 THEN 'X_LARGE' 
              END city_size,
              CASE 
                 WHEN DISCOUNT_ON.DISCOUNT_PERCENTAGE IS NOT NULL 
                   THEN ((DISCOUNT_ON.DISCOUNT_PERCENTAGE / 100) * PRODUCT.RETAIL_PRICE) * SOLD.QUANTITY 
                 WHEN DISCOUNT_ON.DISCOUNT_PERCENTAGE IS NULL 
                   THEN PRODUCT.RETAIL_PRICE * SOLD.QUANTITY 
               END total_rev
      FROM sold 
        JOIN store ON store.store_number = sold.store_number
        JOIN city ON city.city_name = store.city_name
        JOIN discount_on ON sold.pid = discount_on.pid AND sold.date = discount_on.date
        JOIN product ON sold.pid = product.pid
    ) tbl1
    group by date_year,city_size
    order by date_year,city_size