J'opterais probablement pour une daterange colonne.
Cela vous donne la possibilité d'avoir des morceaux de tailles différentes et vous permet de définir un contrainte d'exclusion pour éviter le chevauchement des plages.
Trouver la ligne pour une semaine donnée est encore assez simple en utilisant l'opérateur "contient" @>
, par exemple. where the_column @> to_date('2019-24', 'iyyy-iw')
trouve la ou les lignes contenant le numéro de semaine 24 en 2019.
L'expression to_date('2019-24', 'iyyy-iw')
renvoie le premier jour (lundi) de la semaine spécifiée.
Il est également possible de trouver toutes les lignes comprises entre deux semaines, mais la construction de la plage de dates correspondante semble un peu moche. Vous pouvez soit construire une plage inclusive avec le premier et le dernier jour :daterange(to_date('2019-24', 'iyyy-iw'), to_date('2019-24', 'iyyy-iw') + 6, '[]')
Ou vous pouvez créer une plage avec une plage supérieure exclusive avec le premier jour de la semaine suivante :daterange(to_date('2019-24', 'iyyy-iw'), to_date('2019-25', 'iyyy-iw'), '[)')
Alors que les plages peuvent être indexées assez efficacement et , les index GIST requis sont un peu plus coûteux à maintenir qu'un index B-Tree sur deux colonnes entières.
Un autre inconvénient de l'utilisation de plages (si vous n'avez pas vraiment besoin de flexibilité) est qu'elles occupent plus d'espace que deux colonnes d'entiers (14 octets au lieu de 8, voire 4 avec deux petits entiers). Donc, si la taille de la table est un problème, votre solution actuelle avec les colonnes année/semaine est plus efficace.
Si votre entrée est une date de début et de fin pour commencer (plutôt qu'un "numéro de semaine"), alors j'opterais certainement pour un daterange
colonne. Si ces dates de début et de fin couvrent plus d'une semaine, vous ne stockez qu'une seule ligne, plutôt que plusieurs lignes.