Income sources

PRS for Music

PRSComposition

PRO · CSV · GBP

Configuration

Edit configuration
Display name
PRS for Music
Key
PRS
Rights layer
Composition
File format
CSV
Default currency
GBP
Source kind
PRO

Extraction query

Edit query
Reads CSVUpdated 10/12/2026
SELECT
  row_number() OVER ()                                              AS line_number,
  trim("Work Title")                                                AS song_title,
  upper(trim("Work Title"))                                         AS song_title_key,
  upper(NULLIF(trim("Usage Narrative"), ''))                        AS source_name_key,
  upper(NULLIF(trim("Usage Summary"), ''))                          AS income_class_key,
  upper(NULLIF(trim("Rights Type"), ''))                            AS right_type_key,
  upper(COALESCE(NULLIF(trim("Territory Code"), ''),
                 NULLIF(trim("Territory Name"), '')))               AS territory_raw,
  NULLIF(concat_ws(' / ', NULLIF(trim("IP1"), ''), NULLIF(trim("IP2"), ''),
                          NULLIF(trim("IP3"), ''), NULLIF(trim("IP4"), '')), '')
                                                                    AS writer_name,
  upper(replace(replace(replace(NULLIF(trim("ISWC"), ''), '-', ''), '.', ''), ' ', ''))
                                                                    AS iswc,
  TRY_CAST(NULLIF(trim("Number of Perfs"), '') AS DECIMAL(14,2))    AS units,
  -- Adjustment lines (e.g. fixed point reconciliation) carry no Amount; their
  -- money is the move from the previously paid value to the revised one.
  COALESCE(
    TRY_CAST(replace(NULLIF(trim("Amount (performance revenue)"), ''), ',', '') AS DECIMAL(18,6)),
    CASE WHEN NULLIF(trim("Adjustment Reason"), '') IS NOT NULL THEN
      TRY_CAST(NULLIF(trim("Works Share Transfer To"), '') AS DECIMAL(18,6))
        - COALESCE(TRY_CAST(NULLIF(trim("Works Share Transfer From"), '') AS DECIMAL(18,6)), 0)
    END)                                                            AS amount_raw,
  TRY_CAST(COALESCE(NULLIF(trim("Share"), ''), NULLIF(trim("New Share"), '')) AS DECIMAL(9,6))
                                                                    AS share_percentage,
  COALESCE(NULLIF(trim("Adjustment Reason"), ''),
           NULLIF(trim("Old Share"), ''),
           NULLIF(trim("New Share"), ''),
           NULLIF(trim("Works Share Transfer From"), ''),
           NULLIF(trim("Works Share Transfer To"), '')) IS NOT NULL AS adjustment,
  CAST(try_strptime(NULLIF(trim("Perf Start Date"), ''), '%d/%m/%Y') AS DATE)
                                                                    AS earning_date,
  'GBP'                                                             AS currency,
  to_json(row)                                                      AS source_row
FROM read_csv('{{file}}', header = true, sample_size = -1, all_varchar = true) AS row;

Territory resolution

Edit overrides

territory_raw is resolved to an ISO 3166-1 alpha-2 code in code via a country lookup — not with rules. Values the lookup can't resolve (historical territories, regional groupings) fall back to this override table.

No overrides yet. Every territory value so far resolves through the country lookup.

Normalization rules

Edit rules

This source's own rules, grouped by the attribute each writes. First match wins, top to bottom; conditions within a rule are ANDed. Each group ends in a pinned catch-all.

Stage 1 — Raw match keys to standard enums

income_channel_std

29 rules
1DOWNLOADincome_class_key ~ ONLINE AND source_name_key ~ *PERMANENT DOWNLOAD*
2INTERNET_RADIOincome_class_key ~ ONLINE AND source_name_key ~ *WEBCASTING*
3INTERNET_RADIOincome_class_key ~ ONLINE AND source_name_key ~ *INTERNET RADIO*
4BACKGROUND_MUSICincome_class_key ~ ONLINE AND source_name_key ~ *SOUNDTRACK YOUR BRAND*
5STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ *SERVICE VIDEO
6STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ *YOUTUBE*
7STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ *TIKTOK*
8STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ *INSTAGRAM*
9STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ *FACEBOOK*
10STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ *GEOL*
11STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ *IPLAYER*
12STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ SKY STORE*
13STREAMING_VIDEOincome_class_key ~ ONLINE AND source_name_key ~ PLEX*
14STREAMING_AUDIOincome_class_key ~ ONLINE
15BROADCAST_TVincome_class_key ~ TELEVISION
16BROADCAST_RADIOincome_class_key ~ RADIO
17GENERAL_LICENSINGincome_class_key ~ PUBLIC RECEPTION
18BACKGROUND_MUSICincome_class_key ~ GENERAL RECORDED
19GENERAL_LICENSINGincome_class_key ~ OTHER FEATURED RECORDED
20GENERAL_LICENSINGincome_class_key ~ DISCO
21LIVEincome_class_key ~ CONCERTS
22PRIVATE_COPYINGincome_class_key ~ OVERSEAS AND source_name_key ~ *PRIVATE COPYING*
23ONLINEincome_class_key ~ OVERSEAS AND source_name_key ~ *ONLINE*
24AUDIOVISUALincome_class_key ~ OVERSEAS AND source_name_key ~ *FILMS*
25AUDIOVISUALincome_class_key ~ OVERSEAS AND source_name_key ~ CINEMA*
26GENERAL_AND_BROADCASTincome_class_key ~ OVERSEAS AND source_name_key ~ *GENERAL*
27GENERAL_AND_BROADCASTincome_class_key ~ OVERSEAS AND source_name_key ~ *G&B*
28BROADCAST_RADIOincome_class_key ~ OVERSEAS AND source_name_key ~ *RADIO*
29BROADCAST_TVincome_class_key ~ OVERSEAS
Catch-allUNCLASSIFIEDMatches every line not caught above.

right_type_std

1 rule
1PERFORMANCEright_type_key ~ P
Catch-allUNCLASSIFIEDMatches every line not caught above.

Stage 2 — Standard enums to derived values

is_digital

4 rules
1truenormalized_income_channel ~ STREAMING_*
2truenormalized_income_channel ~ DOWNLOAD
3truenormalized_income_channel ~ INTERNET_RADIO
4truenormalized_income_channel ~ ONLINE
Catch-allfalseMatches every line not caught above.

is_performance

1 rule
1truenormalized_right_type ~ PERFORMANCE AND normalized_income_channel ≠ PRIVATE_COPYING
Catch-allfalseMatches every line not caught above.