简体   繁体   中英

how to use group by clause with 'case' in the below select query

here I need to do group by clause dynamically, howto implement case switch here

 SELECT
    COUNT(*) noofrecords,
    EXTRACT(MONTH FROM start_date) order_by,
    TO_CHAR(TO_DATE(EXTRACT(MONTH FROM start_date), 'MM'), 'month') value
FROM
    tab_name
WHERE
    EXTRACT(YEAR FROM start_date) = 2019
    AND CASE 'MONTH'  ----- getting this value from a variable
        WHEN 'MONTH'   THEN EXTRACT(MONTH FROM start_date)
    END = 2            ----- setting this value from a variable
GROUP BY
    CASE 'YEAR'    ----- getting this value from a variable 
        WHEN 'YEAR'   THEN EXTRACT(MONTH FROM start_date)
    END
ORDER BY
    order_by
    enter code here

You need to have all the expressions in the SELECT clause to either be aggregation functions or in the GROUP BY clause:

DECLARE
  p_cursor      SYS_REFCURSOR;
  p_start_units VARCHAR2(10) := 'YEAR';
  p_year        NUMBER       := 2019;
  p_month       NUMBER       := 2;

  p_out_month   VARCHAR2(10);
  p_out_count   NUMBER;
BEGIN
  OPEN p_cursor FOR
  SELECT COUNT(*) noofrecords,
         TO_CHAR(
           CASE p_start_units
           WHEN 'YEAR' THEN TRUNC( start_date, 'MM' )
           END,
           'month'
         ) AS value
  FROM   tab_name
  WHERE  EXTRACT(YEAR FROM start_date) = p_year
  AND    CASE 'MONTH'
         WHEN 'MONTH' THEN EXTRACT(MONTH FROM start_date)
         END = p_month
  GROUP BY
         CASE p_start_units
         WHEN 'YEAR' THEN TRUNC( start_date, 'MM' )
         END
  ORDER BY
         CASE p_start_units
         WHEN 'YEAR' THEN TRUNC( start_date, 'MM' )
         END;

  LOOP
    FETCH p_cursor INTO p_out_count, p_out_month;
    EXIT WHEN p_cursor%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE( p_out_month || ': ' || p_out_count );
  END LOOP;
END;
/

Test Data :

CREATE TABLE tab_name ( start_date ) AS
  SELECT DATE '2019-01-01' FROM DUAL UNION ALL
  SELECT DATE '2019-01-01' FROM DUAL UNION ALL
  SELECT DATE '2019-02-01' FROM DUAL UNION ALL
  SELECT DATE '2019-02-01' FROM DUAL UNION ALL
  SELECT DATE '2019-02-01' FROM DUAL UNION ALL
  SELECT DATE '2019-03-01' FROM DUAL;

Output :

 february: 3

db<>fiddle here

I would suggest that you use a subquery to define the columns based on the variables and then aggregate and order using them.

Something like this:

SELECT COUNT(*) as noofrecords, order_by, value
FROM (SELECT t.*,
             TO_CHAR(TO_DATE(EXTRACT(MONTH FROM start_date), 'MM'), 'month') as value
             EXTRACT(MONTH FROM start_date) as order_by
             (CASE 'YEAR'    ----- getting this value from a variable 
                   WHEN 'YEAR' THEN EXTRACT(MONTH FROM start_date)
              END) as grouping_var
    END
             (CASE 'MONTH'  ----- getting this value from a variable
                  WHEN 'MONTH' THEN EXTRACT(MONTH FROM start_date)
              END) as filter_criteria
      FROM tab_name
      WHERE EXTRACT(YEAR FROM start_date) = 2019
     ) t
WHERE filter_column = 2  ----- setting this value from a
GROUP BY grouping_var, order_by, value
ORDER BY order_by;

The query doesn't exactly make sense. But I suspect that when you apply to your actually problem, you'll see how this approach helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM