MySQL - Как внутреннее объединение сортирует объединенные данные - PullRequest
2 голосов
/ 05 апреля 2010

Я пытаюсь написать отчет, который объединит человека, его работу и его почасовую оплату труда во время работы.Кажется, я не могу придумать лучший способ присоединиться к стоимости человека, когда дата меньше даты работы.

Скажем, человек в начале года стоил 30 долларов в час, а затем получил 10 долларов.повышение o 5 февраля и еще одно 1 марта.

  • 01/01/2010 $ 30,00 (в час)
  • 02/05 / 2010 $ 40,00
  • 03/01/ 2010 $ 45,00

Человек отводит часы на несколько дней, которые охватывают rasies.

  • 01/05/2010 10 часов (должно быть по 30 $ / час)
  • 01/27/2010 5 часов (опять же по 30 долл. США)
  • 02/10 / 2010 10 часов (по 40 долл. США / час)
  • 03/03/2010 5 часов (при$ 45 / час)

Я пытаюсь написать один SQL-оператор, который вытащит часы, стоимость часа и стоимость часов *.Стоимость - это почасовая ставка, введенная в систему в последний раз, поэтому дата затрат меньше даты работы, упорядоченная по пределу дат затрат 1.

SELECT person.id, person.name, work.hours, person_costs.value, 
       work.hours * person_costs.value AS value
  FROM person
  JOIN work ON person.id = work.person_id
  JOIN person_costs ON person.id = person_costs.person_id 
                   AND person_costs.date < work.date
 WHERE person.id = 1234
ORDER BY work.date ASC

Проблема, с которой я столкнулся, не в person_costsупорядочено по дате в порядке убыванияОн вытягивает «любое» значение (естественно отсортированное по позиции записи), которое соответствует условию.Как выбрать первое значение person_cost, которое старше даты работы?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 05 апреля 2010

Вот моя тестовая схема:

Create Table person_cost
                    (
                    PersonId int not null
                    , Rate decimal(15,4) not null
                    , [date] datetime not null
                    , Constraint PK_person_cost Primary Key Clustered ( PersonId, [date] )
                    )
Insert person_cost(PersonId, Rate, [date]) Values(1,30,'2010-01-01')
Insert person_cost(PersonId, Rate, [date]) Values(1,40,'2010-02-05')
Insert person_cost(PersonId, Rate, [date]) Values(1,50,'2010-03-01')

Create Table Work
                (
                PersonId int not null
                , [Date] datetime not null
                , Hours int not null
                )

Insert Work(PersonId, [Date], Hours) Values(1, '2010-01-05', 10)
Insert Work(PersonId, [Date], Hours) Values(1, '2010-01-27', 5)
Insert Work(PersonId, [Date], Hours) Values(1, '2010-02-10', 10)
Insert Work(PersonId, [Date], Hours) Values(1, '2010-03-03', 5)

И мой запрос:

Select Work.PersonId, Work.Hours, PayRanges.Rate
    , Work.Hours * PayRanges.Rate As Value
From Work
    Join    (
            Select pc1.PersonId, pc1.[date] As StartDate, Rate
                , Coalesce((Select Min(pc2.[date])
                    From person_cost As pc2
                    Where pc2.personId = pc1.personId 
                        And pc2.[date] > pc1.[date])
                    , '9999-12-31') As NextEffectiveDate
            From person_cost As pc1
            ) As PayRanges
        On Work.PersonId = PayRanges.PersonId
            And Work.[Date] >= PayRanges.StartDate
            And Work.[Date] < PayRanges.NextEffectiveDate

По сути, я рассчитал дату окончания эффективной ставки заработной платы.В моем примере я исключил соединение с таблицей Person, однако его можно легко включить для получения данных Person.Обратите внимание, что мой расчет даты истечения срока выплаты будет осуществляться в день, когда вступит в силу следующий размер выплаты, и поэтому я запрашиваю стоимость, строго меньшую даты истечения срока действия.

0 голосов
/ 05 апреля 2010

Лучшее решение - изменить таблицу person_costs так, чтобы она записывала цену за интервал времени (начало и конец), а не цену после изменения. Пока вы не создадите никаких перекрывающихся интервалов, объединение всегда будет получать только одну строку на человека / дату.

Если вы не можете изменить структуру таблицы, вы можете создать представление, которое достигает того же эффекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...