Как использовать неагрегированные столбцы, используемые в предложении SELECT, не используя его в предложении GROUP BY? - PullRequest
0 голосов
/ 10 января 2020

Я выполняю этот запрос и получаю правильный результат

SELECT
         CONCAT("year", ' - ', TRIM('20' FROM "year") + 1) as 'Years',
         SUM("svalue") as 'Value',
         'Sale' as 'Type',
         "year" as 'Year',
         "code" as 'FACode',
FROM  "FCJOIN" 
WHERE    "code"  IN
    (
    SELECT "fccode"
    FROM  "fcdetails" 
    )
 AND    "month"  between '04'  and  '12'
 AND    "year"  IN ( '2016'  , '2017'  , '2018'  , '2019'  )
GROUP BY "code", "year" 

, что мне нужно, если я добавлю новый столбец formonth , он даст ошибка Неправильное использование предложения GROUP BY? Убедитесь, что все неагрегированные столбцы, используемые в предложении SELECT, также используются в предложении GROUP BY.

это мой измененный запрос, подобный этому

SELECT
         CONCAT("year", ' - ', TRIM('20' FROM "year") + 1) as 'Years',
         SUM("svalue") as 'Value',
         'Sale' as 'Type',
         "year" as 'Year',
         "code" as 'FACode',
         **"formonth" as 'Period'**
FROM  "FCJOIN" 
WHERE    "code"  IN
    (
    SELECT "fccode"
    FROM  "fcdetails" 
    )
 AND    "month"  between '04'  and  '12'
 AND    "year"  IN ( '2016'  , '2017'  , '2018'  , '2019'  )
GROUP BY "code", "year"

есть ли способ сделать это правильная группировка или или есть какой-нибудь способ переписать? Я не хочу, чтобы вновь добавленный столбец в группе по предложению. Я пытаюсь это в отчетах Zoho. Любая помощь ?

1 Ответ

1 голос
/ 11 января 2020

Если вы хотите показывать месяцы каждого года, для которого применялся код, вы можете объединить их описания / строки с помощью string_agg (). Для нескольких уровней агрегации, т. Е. Сумма (значение), группа по (код, год) или группа по (год, описание месяца / период) могут использоваться ГРУППОВЫЕ НАБОРЫ.

declare @fcdetails table (fccode int)
insert into @fcdetails(fccode) values(1), (2), (3);

declare @fcjoin table
(
    [year] char(4),
    [month] tinyint,
    svalue int,
    code int
) ;

insert into @fcjoin([year], [month], svalue, code)
values
('2016', 5, 10, 1), ('2016', 6, 10, 1), ('2016', 7, 10, 1), 
('2017', 5, 4, 2), ('2017', 6, 4, 2), 
('2018', 7, 10, 3);

declare @othertable table
(
[themonth] tinyint,
period varchar(20)

);

insert into @othertable([themonth], period)
select distinct [month], {fn MONTHNAME(datefromparts('2020', [month], 1))}
from @fcjoin;


SELECT 
         CONCAT("year", ' - ', TRIM('20' FROM "year") + 1),
         SUM("svalue") as 'Value',
         'Sale' as 'Type',
         "year" as 'Year',
         "code" as 'FACode',
         string_agg(o.period, ',') as forperiod

FROM  @FCJOIN as f
join @othertable as o on f.month = o.themonth --careful with joins & aggregations
WHERE    "code"  IN
    (
    SELECT "fccode"
    FROM  @fcdetails
    )
 AND    "month"  between '04'  and  '12'
 AND    "year"  IN ( '2016'  , '2017'  , '2018'  , '2019'  )
GROUP BY "code", "year"; 

SELECT 
         CONCAT("year", ' - ', TRIM('20' FROM "year") + 1),
         SUM("svalue") as 'Value',
         'Sale' as 'Type',
         "year" as 'Year',
         "code" as 'FACode',
         (select string_agg(o.period, ',') 
         from @othertable as o
         where o.themonth in
         (select b.month from @FCJOIN as b where b.year = f.year and b.code = f.code) 

         ) as forperiod

FROM  @FCJOIN as f
WHERE    "code"  IN
    (
    SELECT "fccode"
    FROM  @fcdetails
    )
 AND    "month"  between '04'  and  '12'
 AND    "year"  IN ( '2016'  , '2017'  , '2018'  , '2019'  )
GROUP BY "code", "year"; 

SELECT 
         CONCAT("year", ' - ', TRIM('20' FROM "year") + 1),
         SUM("svalue") as 'Value',
         'Sale' as 'Type',
         "year" as 'Year',
         "code" as 'FACode',
         o.period as forperiod

FROM  @FCJOIN as f
join @othertable as o on f.month = o.themonth --careful with joins & aggregations
WHERE    "code"  IN
    (
    SELECT "fccode"
    FROM  @fcdetails
    )
 AND    "month"  between '04'  and  '12'
 AND    "year"  IN ( '2016'  , '2017'  , '2018'  , '2019'  )
GROUP BY GROUPING SETS(("code", "year"),("year", o.period) /*,(code, o.period)*/);
...