콘텐츠로 이동

2023 06 23

2023-06-23

Slick Group By

참고: https://scala-slick.org/doc/3.0.0/sql-to-slick.html#groupby

  • 개요
    • 기존의 SQL과는 약간 다른 시그니처를 포함하고 있다
      • SQL의 group by는 그룹핑 키랑 무관한 모든 컬럼을 반환하기도
      • avg 같은 통합연산을 통해 하나의 value를 반환하기도 한다
        select ADDRESS_ID, AVG(AGE)
        from PERSON
        group by ADDRESS_ID
        
  • Slick의 경우 grouping key를 기반으로 List 의 Map 형태로 반환
    • Map(key -> List(row))
    • 자동으로 변환해주는 것은 아니고, 명시적으로 스칼라에서 처리해줘야 함
    • SQL에서는 grouped value에 대해서는 aggregate를 강요하기 때문에 슬릭에서 역시 동일하게 강요한다
    • 즉, Slick의 groupBy는 map을 통해 뚝딱 aggregation 처리해줘야 한다는 것
      people.groupBy(p => p.addressId)
          .map { case (addressId, group) => (addressId, group.map(_.age).avg) }
      
  • 예시 테이블
    case class Employee(id: Int, name: String, department: String)
    
    class Employees(tag: Tag) extends Table[Employee](tag, "employees") {
        def id: Rep[Int] = column[Int]("id", O.PrimaryKey)
        def name: Rep[String] = column[String]("name")
        def department: Rep[String] = column[String]("department")
    
        def * : ProvenShape[Employee] = (id, name, department).mapTo[Employee]
    }
    
    val employees = TableQuery[Employees]
    
  • Group By를 Slick에서 쓰는 법
    val groupByQuery = employees
        .groupBy(_.department)
        .map {
            case (department, group) => (department, group.length)
        }
    

    - groupBy - 해당 column || expression 으로 GroupBy 해주세요 - map - 각각의 그룹화된 결과값을 본인이 원하는대로 바꾸기 위함 - 이 상황에서는 (department, group) => (department, group.length)로 변경

Slick Subquery

참고: https://scala-slick.org/doc/3.0.0/sql-to-slick.html#subquery

  • 개요
    • Slick의 Query는 타입만 맞다면 조합이 가능하다
    • Slick의 .in은 sub-query를 기대한다
    • Slick의 .inSet은 인메모리 스칼라 컬렉션을 기반으로 동작할 수 있다

Future에 map, flatMap