2011-08-15 3 views
3

У меня есть сторонняя таблица, заполняемая некоторыми загроможденными данными, которые мне нужны, чтобы получить самые последние записи. Таблица будет получать новую строку каждый год или каждый раз, когда изменяется «Лицо». Таблица работает на основе того, что последний ActiveDate является правильным человеком. Я создал макет таблицы и данные, чтобы показать это.Выбор отдельных записей без использования временной таблицы

CREATE TABLE `Persons` (
    `PersonId` varchar(200) NOT NULL, 
    `Name` varchar(200) NOT NULL DEFAULT '', 
    `ActiveDate` varchar(25) NOT NULL, 
    `ExpireDate` varchar(25) DEFAULT NULL, 
    `Job` varchar(200) NOT NULL DEFAULT '', 
    `Position` varchar(200) NOT NULL DEFAULT '' 
) 

И некоторые издеваться данные:

Id  |`Name`  |ActiveDate    |ExpireDate    |Job  |`Position` 
--------------------------------------------------------------------------------------------------- 
J1234 |Doe, John  |2010-08-15 00:00:00  |2011-08-15 00:00:00 |Worker |Janitor 
J1234 |Doe, John  |2011-08-15 00:00:00  |0000-00-00 00:00:00 |Worker |Janitor 
777  |Doe, Jane  |2010-06-04 00:00:00  |0000-00-00 00:00:00 |Boss  |Janitor 
777  |Doe, Jane  |2011-04-30 00:00:00  |0000-00-00 00:00:00 |Boss  |Janitor 
654G  |Smith, Jane |2011-01-20 00:00:00  |0000-00-00 00:00:00 |Worker |Janitor 

В таблице также имеет и EXPIREDATE столбец, который фактически установлен конечным пользователем, и не всегда устанавливается к моему ужасу. В настоящее время я использую фиктивную таблицу, чтобы вытащить отдельные записи и сохранить их в течение дня. Я бы использовал временную таблицу, но я не уверен на 100%, как в MySQL, плюс я их не люблю. То, как я это делаю, просто временно в надежде на лучший SQL.

Затем данные должны быть соединены с множеством других таблиц, чтобы получить готовый продукт. Но мне все еще нужно иметь дело с первоначальным набором различных данных. И соединение в другой таблице с самого начала просто не сработает.

Так вот, как я потянув мои данные, хранить его, а затем потянув ее позже и joing его к другим таблицам:

INSERT INTO tmp_Person (Id, `Name`, Job, `Position`) 
    SELECT DISTINCT Id, `Name`, Job, `Position` 
    FROM Person 

SELECT tmp_Person.Id, 
    tmp_Person.`Name`, 
    tmp_Person.Job, 
    tmp_Person.`Position`, 
    Pricing.Cost, 
    Pricing.Benefit 

    FROM tmp_Person 
    LEFT OUTER JOIN Pricing AS CL ON CL.PersonId = tmp_Person.Id 
     AND CL.PriceScredule = 'Major-Client' 
     AND CL.ExpireDate = '0000-00-00 00:00:00' 
    LEFT OUTER JOIN Pricing AS Inter ON Inter.PersonId = tmp_Person.Id 
     AND Inter.PriceScredule = 'Internal-Client' 
     AND Inter.ExpireDate = '0000-00-00 00:00:00' 

Как я могу написать это, чтобы избежать затрат на обработку из повторяющиеся строки с использованием временной таблицы (в любой форме)? Хоть я сделал это достаточно ясно, если не могу с радостью добавить или уточнить.

+0

Возможно ли иметь две строки с одинаковым идентификатором '' '' ', но отличающиеся' Name' или 'Job' или' Position'? Если нет, запрос может быть оптимизирован. –

+0

Нет, это действительно уникальный столбец в моих данных. Это также для этой другой базы данных, просто не в этих данных. Я добываю данные из сторонних биллинговых систем, где они просто отправляют нам этот бесконечный поток данных ежедневно. Затем я рыбу и вытаскиваю то, что нам нужно. Я пытаюсь поддерживать устаревшую систему, наполненную странностями, с данными от третьей стороны, которая полна много странностей. Все с моим кодом, который, надеюсь, ... не странность. –

+0

Возможно, вам не следует дважды присоединяться к таблице «Цены», так как тогда вам будет разрешено использовать псевдоним «Ценообразование» (при условии, что он не будет изменен). Как бы то ни было, вы не можете ссылаться на «Ценообразование» в предложении SELECT, оно должно быть либо «CL», либо «Inter». –

ответ

3

Заменить tmp_Person с кодом у вас есть для временной таблицы:

SELECT tmp_Person.Id, 
    tmp_Person.`Name`, 
    tmp_Person.Job, 
    tmp_Person.`Position`, 
    CL.Cost  AS MajorCost,    
    CL.Benefit AS MajorBenefit, 
    Inter.Cost AS InternalCost, 
    Inter.Benefit AS InternalBenefit 

    FROM 
     (SELECT DISTINCT Id, `Name`, Job, `Position` 
     FROM Person 
    ) 
     AS tmp_Person 
    LEFT OUTER JOIN Pricing AS CL ON CL.PersonId = tmp_Person.Id 
     AND CL.PriceScredule = 'Major-Client' 
     AND CL.ExpireDate = '0000-00-00 00:00:00' 
    LEFT OUTER JOIN Pricing AS Inter ON Inter.PersonId = tmp_Person.Id 
     AND Inter.PriceScredule = 'Internal-Client' 
     AND Inter.ExpireDate = '0000-00-00 00:00:00' 

Как заметил @Andriy, используя Pricing.Cost или Pricing.Benefit в списке выбора вызовет ошибку. Наверное, ты забыл изменить его, когда отправляешь сообщение.

+0

Я попробую это с первого утра. Это обязательно сэкономит гораздо больше времени. Еще больше, поскольку база данных стареет (надеюсь, изящно). –

+2

Вы копируете ошибку OP, ссылаясь на 'Pricing' вместо' CL' или 'Inter' (в предложении SELECT). –

+0

@ Энди: Тинкс, не заметил этого. –

-1

Поместите это вместе, прежде чем я понял, что вопрос задан для mysql, но главный должен быть таким же, это даст вам запись для каждого PersonID с самой последней таблицей ActiveDate from Person.

select * 
from 
(
select persons.*, ROW_NUMBER() over(partition by personid order by personid, activedate desc) as rn 
from persons 
) basedata 
where basedata.rn=1 
+0

К сожалению, у MySQL нет 'ROW_NUMBER()' и нет 'OVER()'. Никаких аналитических функций вообще. –

Смежные вопросы