@@ -8,6 +8,7 @@ use bios_basic::spi::{
8
8
use itertools:: Itertools ;
9
9
use tardis:: {
10
10
basic:: { dto:: TardisContext , error:: TardisError , result:: TardisResult } ,
11
+ chrono:: format,
11
12
db:: {
12
13
reldb_client:: TardisRelDBClient ,
13
14
sea_orm:: { self , FromQueryResult , Value } ,
@@ -243,7 +244,8 @@ pub async fn query_metrics(query_req: &StatsQueryMetricsReq, funs: &TardisFunsIn
243
244
rel_external_id : None ,
244
245
query_limit,
245
246
} ) ;
246
-
247
+ // todo 需要更改使用with
248
+ let ct_agg = query_req. group . iter ( ) . any ( |i| i. code == "ct" ) ;
247
249
let conf_limit = query_limit;
248
250
// Dimension configuration, used for group and group_order
249
251
// 纬度配置,用于group以及group_order
@@ -449,7 +451,7 @@ pub async fn query_metrics(query_req: &StatsQueryMetricsReq, funs: &TardisFunsIn
449
451
group. code. clone( ) ,
450
452
group. time_window. as_ref( ) . map( |i| i. to_string( ) . to_lowercase( ) ) . unwrap_or( "" . to_string( ) )
451
453
) ;
452
- sql_part_group_infos. push ( ( column_name_with_fun, alias_name, col_conf. show_name . clone ( ) ) ) ;
454
+ sql_part_group_infos. push ( ( column_name_with_fun, alias_name, col_conf. show_name . clone ( ) , col_conf . col_key . clone ( ) ) ) ;
453
455
} else {
454
456
return Err ( funs. err ( ) . not_found (
455
457
"metric" ,
@@ -464,12 +466,12 @@ pub async fn query_metrics(query_req: &StatsQueryMetricsReq, funs: &TardisFunsIn
464
466
) ) ;
465
467
}
466
468
}
467
- let sql_part_groups = sql_part_group_infos. iter ( ) . map ( |group| group. 1 . clone ( ) ) . collect :: < Vec < String > > ( ) . join ( "," ) ;
469
+ let mut sql_part_groups = sql_part_group_infos. iter ( ) . map ( |group| group. 1 . clone ( ) ) . collect :: < Vec < String > > ( ) . join ( "," ) ;
468
470
469
471
// Package outer select
470
472
// (column name with fun, alias name, show_name, is dimension)
471
473
let mut sql_part_outer_select_infos = vec ! [ ] ;
472
- for ( column_name_with_fun, alias_name, show_name) in sql_part_group_infos {
474
+ for ( column_name_with_fun, alias_name, show_name, _ ) in sql_part_group_infos. clone ( ) {
473
475
sql_part_outer_select_infos. push ( ( column_name_with_fun, alias_name, show_name, true ) ) ;
474
476
}
475
477
for select in & query_req. select {
@@ -489,7 +491,35 @@ pub async fn query_metrics(query_req: &StatsQueryMetricsReq, funs: &TardisFunsIn
489
491
"500-spi-stats-internal-error" ,
490
492
)
491
493
} ) ?;
492
- let column_name_with_fun = col_data_type. to_pg_select ( & format ! ( "_.{}" , select. code. clone( ) ) , & select. fun ) ;
494
+ let column_name_with_fun = if ct_agg {
495
+ if select. code != "_count" {
496
+ sql_part_groups = format ! ( "{},_.{}" , sql_part_groups, select. code. clone( ) ) ;
497
+ }
498
+ let mut partition_dim = vec ! [ ] ;
499
+ let mut order_dim = "" . to_string ( ) ;
500
+ for ( column_name_with_fun, _, _, col_key) in sql_part_group_infos. clone ( ) {
501
+ if col_key == "ct" {
502
+ order_dim = column_name_with_fun. clone ( ) ;
503
+ } else {
504
+ partition_dim. push ( column_name_with_fun) ;
505
+ }
506
+ }
507
+ format ! (
508
+ "{} OVER ({})" ,
509
+ col_data_type. to_pg_select(
510
+ & format!( "_.{}" , if select. code == "_count" { "count" . to_string( ) } else { select. code. clone( ) } ) ,
511
+ & select. fun
512
+ ) ,
513
+ if partition_dim. len( ) > 0 {
514
+ format!( "PARTITION BY {} ORDER BY {}" , partition_dim. join( "," ) , order_dim)
515
+ } else {
516
+ format!( "ORDER BY {}" , order_dim)
517
+ }
518
+ )
519
+ } else {
520
+ col_data_type. to_pg_select ( & format ! ( "_.{}" , select. code. clone( ) ) , & select. fun )
521
+ } ;
522
+ // let column_name_with_fun = col_data_type.to_pg_select(&format!("_.{}", select.code.clone()), &select.fun);
493
523
let alias_name = format ! ( "{}{FUNCTION_SUFFIX_FLAG}{}" , select. code. clone( ) , select. fun. to_string( ) . to_lowercase( ) ) ;
494
524
sql_part_outer_select_infos. push ( ( column_name_with_fun, alias_name, col_conf. show_name . clone ( ) , false ) ) ;
495
525
}
@@ -603,6 +633,7 @@ pub async fn query_metrics(query_req: &StatsQueryMetricsReq, funs: &TardisFunsIn
603
633
} else {
604
634
"fact.own_paths LIKE $1" . to_string ( )
605
635
} ;
636
+ // todo 提供另一种with语法的实现,用于 ct 统计全表数据
606
637
let final_sql = format ! (
607
638
r#"SELECT {sql_part_outer_selects}{}
608
639
FROM (
@@ -640,14 +671,22 @@ pub async fn query_metrics(query_req: &StatsQueryMetricsReq, funs: &TardisFunsIn
640
671
if query_req. ignore_distinct. unwrap_or( false ) {
641
672
""
642
673
} else if mes_distinct {
643
- "DISTINCT ON (fact.key) fact.key AS _key,"
674
+ if ct_agg {
675
+ "DISTINCT ON (fact.key,date_part('day',fact.ct)) fact.key AS _key,"
676
+ } else {
677
+ "DISTINCT ON (fact.key) fact.key AS _key,"
678
+ }
644
679
} else {
645
680
""
646
681
} ,
647
682
if query_req. ignore_distinct. unwrap_or( false ) {
648
683
""
649
684
} else if mes_distinct {
650
- "_key,"
685
+ if ct_agg {
686
+ "_key,date_part('day',fact.ct),"
687
+ } else {
688
+ "_key,"
689
+ }
651
690
} else {
652
691
""
653
692
} ,
0 commit comments