SOQL-запрос для получения записей

Мне нужно запросить объект с именем trans__c, который имеет следующие поля

 id,
 scantime__c // datetime
 name
 asset__c // external id
 status

Мне нужно получить только данные, которые имеют статус ожидания, и если есть какие-либо повторяющиеся активы, мне нужно получить только запись со временем сканирования как самую последнюю.

Например,

Если есть 3 записи

   asset         name      scantime              Status

    1            Rec 1      17-dec-2011 13:10     Pending
    1            Rec2       17-dec-2011 13:50     Pending
    2            Rec3       17-dec-2011 13:10     Pending

Результат запроса должен быть

    1            Rec2       17-dec-2011 13:50     Pending
    2            Rec3       17-dec-2011 13:10     Pending

person Prady    schedule 17.12.2011    source источник


Ответы (2)


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

Возможно, это неправильный подход, но я бы взял все записи «Ожидание», а затем выполнил логику в коде (при условии, что у вас нет массы результатов):

map<integer, Trans__c> mapAssetToRecord = new map<integer, Trans__c>();

for(Trans__c [] sTransArr : [select Id, Name, Asset__c, Scan_Time__c, Status__c
                               from Trans__c
                              where Status__c = 'Pending'])
{
    for(Trans__c sTrains : sTransArr)
    {
        if(mapAssetToRecord.get(sTrans.Asset__c) == null)
        {
            mapAssetToRecord.put(sTrans.Asset__c, sTrans);
        }
        else if(sTrans.Scan_Time__c > mapAssetToRecord.get(sTrans.Asset__c).Scan_Time__c)
        {
            mapAssetToRecord.put(sTrans.Asset__c, sTrans);
        }
    }
}

// now mapAssetToRecord includes all of the records you want

Возможно, есть более элегантное решение, использующее какой-нибудь хитрый SOQL, но сейчас оно ускользает от меня (в конце концов, сегодня воскресное утро, а я только что позавтракал!).

person Matt Lacey    schedule 17.12.2011
comment
Я считаю, что после выполнения GROUP BY для Id будут извлечены все записи, которых нет в агрегатной функции, поскольку Id уникален. Таким образом, вызов MAX() и последующее выполнение GROUP BY для всех других полей, начинающихся с Id, должно извлекать все необходимые записи (все, для которых указано максимальное значение — в данном случае datetime). По крайней мере, так он ведет себя в моем браузере схем :) - person Adam; 18.12.2011
comment
Если подумать, возможно, вы правы. Агрегированные запросы в SOQL немного сбивают с толку. - person Adam; 18.12.2011
comment
Да, я практически никогда не нахожу их полезными, если только я действительно не хочу суммировать, считать или усреднять! - person Matt Lacey; 18.12.2011

Ваш запрос будет выглядеть так:

SELECT Id, MAX(scantime__c), Name, asset__c, status
FROM trans__c WHERE status = 'Pending' 
GROUP BY Id, Name, asset__c, status

Ваше здоровье

[РЕДАКТИРОВАТЬ]

Похоже, что агрегированный запрос вернет дополнительные строки, которые вы хотите опустить, поэтому, возможно, то, что предлагает Лейси, будет работать лучше для вас. Но агрегаты могут быть действительно полезными при правильном применении. Удачи.

person Adam    schedule 17.12.2011
comment
На самом деле я создал объект, чтобы поиграть с этим, даже используя GROUP BY (и помещая Asset__s первым), я все равно получаю 3 возвращаемые записи, потому что нам также нужно сгруппировать по имени и идентификатору, если мы хотим, чтобы эти поля возвращались в запросе. - person Matt Lacey; 18.12.2011