您如何将数字(薪水)映射到范围?

时间:2019-03-18 05:37:22

标签: sql postgresql join

我有薪水数据,我试图将它们映射回另一个表中的范围。

例如,salary表:

| id | amount | currency | 
|----+--------+----------|
|  A |  11111 |      USD |
|  B |   5000 |      EUR | 
|  C |  45000 |      RMB |
|  D | 100000 |      USD |
|  E | 110000 |      EUR |
|  F |  67000 |      RMB |

我有另一个表bands_pay,其中有一个label表示工资范围。例如:

| label |       range     | currency | 
|-------+-----------------+----------|
|    1A |   10000 - 15000 |      USD |
|    2C | 100000 - 149999 |      EUR | 
|    3P |   25000 - 49999 |      RMB |
|    4F |   35000 - 49999 |      EUR |
|    5B |     5000 - 9999 |      EUR |
|    6Q | 100000 - 124999 |      USD |
|    7F |   50000 - 74999 |      RMB |

如何联接这些表以返回salary表的所有内容,并返回正确的label

| id | amount | currency | label |
|----+--------+----------+-------|
|  A |  11111 |      USD |    1A |
|  B |   5000 |      EUR |    5B |
|  C |  45000 |      RMB |    3P |
|  D | 100000 |      USD |    6Q |
|  E | 110000 |      EUR |    2C |
|  F |  67000 |      RMB |    7F |

3 个答案:

答案 0 :(得分:0)

您应将范围列分为两列:

-标签-开始范围-结束范围-货币

然后:

select salary.id,salary.amount,salary.currency,bands_pay.range
from salary,bands_pay
where
bands_pay.start_range<=salary.amount and salary.amount<bands_pay.end_range

答案 1 :(得分:0)

您可以为此使用numrange。说明here

例如:

With SalaryRanges(SalaryRange) AS (
VALUES(NumRange(0,5000)), (Numrange(5000,10000)), (NumRange(10000,15000)), (NumRange(15000,25000)), (NumRange(25000,50000)), (NumRange(50000,100000)), (NumRange(100000,150000))
),
Salary(id, amount, currency, label) as (
    SELECT UNNEST(ARRAY['A','B','C','D','E','F']),
    UNNEST(ARRAY[11111,5000,45000,100000,110000,670000]::numeric[]),
    UNNEST(ARRAY['USD','EUR', 'RMB', 'USD','EUR', 'RMB']),
    UNNEST(ARRAY['1A','5B','3P','6Q','2C','7F'])
)
SELECT *
FROM Salary S
JOIN SalaryRanges SR on SalaryRange @> Amount

如果您决定将范围存储到表中,则可能需要创建一个exclusion constraint
否则,您需要决定如何处理重叠范围。

答案 2 :(得分:0)

由于您的范围值不在单独的列中(如果更好),您需要先使用range来拆分regexp_split_to_array列,然后将两个表联接起来并检查哪个范围适合每个薪水的数额:

select s.id, s.amount, s.currency, bp.label from salary s join (
select a[1] as from, a[2] as to
from (
    select regexp_split_to_array(range, '-')
    from bands_pay
     ) as dt(a)) bp
on s.id >= bp.from and s.id <= bp.to