2014-10-21 3 views
3

SQL-запрос, который я написал, получил 3677 строк, где поле cutomerID содержит много повторяющихся данных. Я хочу написать запрос, который даст мне все необходимые поля с уникальным cutomerID. Мы не можем использовать разные для customerID только в том случае, если другие поля имеют другой тип данных. Пожалуйста, помогите мне с этим запросом:Нужна помощь с SQL-запросом для извлечения данных

SELECT TimeMark, 
     CustomerID, 
     AccountId, 
     TargetURL 
    FROM BTILog 
    WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
    ORDER BY TimeMark DESC 

Please have a look the data I am getting from the below query. There you can see duplicate customerID as highlighted in blue line. I want the 57155299 customer only once with last time mark, similarly if there will be any other customer who have appeared twice/thrice or so on, theey should only once in my data extract

+1

вам нужно только одну запись для каждого клиента делать? Или вам нужны они, сгруппированные по клиенту. Если вы не можете использовать разные, это потому, что записи в целом не отличаются друг от друга, и, естественно, это дает вам разные результаты. Если эти данные неактуальны, пожалуйста, уточните более подробную информацию. – trnelson

+0

Мне нужна отдельная запись клиента в целом со всеми четырьмя полями. группировка по клиенту будет в порядке. У меня не было репутации 10, иначе я отправлю изображение того, что в настоящее время я не хочу. пожалуйста, сообщите им, если вам потребуется больше разъяснений. – user3259712

+0

@trnelson Я отредактировал свое сообщение и посмотрю, имеет ли это смысл. – user3259712

ответ

0

Я считаю рейтинг ваш результат даст вам желаемый результат. Аналогично этому.

select TimeMark, 
     CustomerID, 
     AccountId, 
     TargetURL 
    from (
     select TimeMark, 
      CustomerID, 
      AccountId, 
      TargetURL, 
      rank() over (
       CustomerID order by TimeMark desc 
       ) rank_ 
     from BTILog 
     where timemark between '20140926 00:00:00' 
       and '20141020 23:59:59' 
      and TargetURL like '%/api/v1/cust/details%' 
      and Class like 'com.btfin.security.sso.SSODetailsFactory%' 
     ) 
    where rank_ = 1; 

Вы также можете включить AccountId в свой раздел, если это ваш желаемый результат.

rank() over (
        CustomerID, AccountId order by TimeMark desc 
        ) rank_ 

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

+0

Спасибо. Раньше я раньше не пользовался функцией ранжирования, но, конечно же, попробую это, и у вас будет больше об этом. – user3259712

-1

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

SELECT TimeMark, 
     CustomerID, 
     COUNT(CustomerID) AS duplicate, 
     AccountId, 
     TargetURL 
    FROM BTILog 
    WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
    GROUP BY(CustomerID) 
    ORDER BY TimeMark DESC 
+0

Спасибо Эдварду, он выглядел более убедительно. – user3259712

+1

жаль, что так поздно возвращаюсь к вам. но выполнение нашего запроса вернуло ошибку ниже: Msg 8120, Level16, State1, Line2 Column BTILog.TimeMark недопустим в списке выбора, потому что он не содержится ни в агрегатной функции, ни в предложении GROUP BY. Пожалуйста помоги. – user3259712

0

Попробуйте

Select distinct CustomerId, AccountId, TargetURL, 
       Max(TimeMark) over (partition by CustomerId) as 'MaxTM' 
    FROM BTILog 
    WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
    group by CustomerId, AcconutId, TargetUrl --I don't think this is needed 
    ORDER BY MaxTM DESC 
+0

@C Sharper: Спасибо, помощник. Я обязательно попробую и вернусь. – user3259712

+0

@C: Привет, выполнив ваш запрос, я получил следующую ошибку: «BTILog.TimeMark недействителен в списке выбора, потому что он не содержится ни в агрегатной функции, ни в предложении GROUP BY. Предложение ORDER BY должно появиться в списке выбора, если указан параметр SELECT DISTINCT. – user3259712

+0

Я думаю, что проблема заключается в том, что мы не указываем имя столбцу, в котором мы занимаемся секционированием, а затем пытаемся упорядочить этот столбец. См. Мое редактирование. Потому что 'Max (TimeMark) over (раздел CustomerId) <> TimeMark', который был в нашем заказе на – CSharper

0

Каждое выбранное поле должно быть либо частью группы по или агрегируются (как MAX, SUM, COUNT и т. Д.) Похоже, что в вашем случае вам нужно группировать объекты CustomerID, AccountId и, возможно, TargetURL (если они все одинаковые, группируйте, если нет, возможно MAX (TargetURL)) и выясните, что вы хотите сделать с TimeMark - MAX (TimeMark), возможно?

Вы можете попробовать одно из следующих действий, в зависимости от характера TargetURL:

 
SELECT MAX(TimeMark), CustomerID, AccountId, TargetURL 
FROM BTILog 
WHERE timemark BETWEEN '20140926 00:00:00' 
    AND '20141020 23:59:59' 
    AND TargetURL LIKE '%/api/v1/cust/details%' 
    AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
CustomerID, AccountId, TargetURL 
ORDER BY TimeMark DESC 

или

 
SELECT MAX(TimeMark), CustomerID, AccountId, MAX(TargetURL) 
FROM BTILog 
WHERE timemark BETWEEN '20140926 00:00:00' 
    AND '20141020 23:59:59' 
    AND TargetURL LIKE '%/api/v1/cust/details%' 
    AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
GROUP BY CustomerID, AccountId 
ORDER BY TimeMark DESC 
-1

Вы можете написать подзапрос, чтобы выбрать DISTINCT только из CustomerID.

SELECT TimeMark, 
     (SELECT DISTINCT CustomerID 
     FROM BTILog 
     WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%') 
     AS CustyID, 
     AccountId, 
     TargetURL 
    FROM BTILog 
    WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
    ORDER BY TimeMark DESC 
+0

По вашему запросу у меня возникла следующая ошибка: Msg 512, уровень 16, состояние 1, строка 2 Подзапрос возвратил более 1 значения. Это недопустимо, когда подзапрос следует =,! =, <, <= , >,> = или когда подзапрос используется как выражение. – user3259712

0

вам нужно использовать подзапрос, чтобы вернуть запись с максимальным TimeMark, на основе критериев, а затем присоединиться на CustomerID и TimeMark, это ограничит результат записи, которую вы хотите

SELECT BTILog.TimeMark, BTILog.CustomerID, BTILog.AccountID, BTILog.TargetUrl 
FROM BTILog 
INNER JOIN (
    SELECT Max(BTILog.TimeMark) AS MaxOfTimeMark, BTILog.CustomerID 
    FROM BTILog 
    WHERE (((BTILog.TargetUrl) Like '%/api/v1/cust/details%') 
    AND ((BTILog.Class) Like 'com.btfin.security.sso.SSODetailsFactory%') 
    AND ((BTILog.TimeMark) BETWEEN '20140926 00:00:00' AND '20141020 23:59:59')) 
    GROUP BY BTILog.CustomerID) AS T1 
ON (BTILog.CustomerID = T1.CustomerID) 
    AND (BTILog.TimeMark = T1.MaxOfTimeMark) 
ORDER by BTILog.TimeMark DESC 

Я обычно работаю в редакторе запросов MS Access, поэтому синтаксис отличается, я думаю, что я изменил все, что может привести к его «падению»

-1

Вам, по всей вероятности, необходимо перепроектировать структуру данных для разделения данных в две таблицы, один определяющий Клиент, а другой - как отметка времени. Каждая запись клиента будет уникальной, с использованием или без использования DISTINCT. Таблица Time Stamp будет ссылаться на таблицу клиентов через внешний ключ, аналогичное поле CustomerID и временную метку вместе с любыми другими полями, которые необходимо записать на каждом периодическом событии. Схематически:

Заказчик: CustomerID, Integer, Unique.
AccountID, Integer.
TargetURL, текст 250.

TimeStamp: TimeID, Integer, Unique.
TimeMark, DateTime.
CustomerID, Integer

Идентификатор пользователя от клиентов и TimeID от TimeStamp, вероятно, должен быть полем AutoIncrement 'Crash Number'. Поля CustomerID в каждой таблице действуют как ссылка. С помощью этой рационализированной схемы ваши запросы начнут легко вставать на свои места, и вы сможете извлекать нужные данные без сложностей, таких как DISTINCT и UNIQUE ROWS.

0

Исходя из ваших данных образца и учитывая, что ваш запрос верен, тогда.

Select * from 
(SELECT TimeMark, 
     CustomerID, 
     AccountId, 
     TargetURL, 
     **ROW_NUMBER()over(partition by CustomerID order by TimeMark desc)rownum** 
    FROM BTILog 
    WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
    ORDER BY TimeMark DESC 
    ) tbl where rownum=1 
0

Я не думаю, что функция rank или rownum уловок поможет, так как вы не имеете дело с отсортированного списка тех же самых уникальных ключей, но для каждого CustomerID, A.AccountId вы ищете для записи, что находится в пределах определенного периода времени, который имеет максимальную отметку времени

Вы можете попробовать это:

SELECT DISTINCT 
     A.BTimeMark, 
     A.CustomerID, 
     A.AccountId, 
     A.TargetURL 
    FROM BTILog A 
    WHERE A.timemark = 
    (
      SELECT MAX(B.TimeMark) 
      FROM BTILog B 
      WHERE B.timemark BETWEEN '20140926 00:00:00' AND '20141020 23:59:59' 
      AND B.TargetURL LIKE '%/api/v1/cust/details%' 
      AND B.Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 

      AND B.CustomerID = A.CustomerID 
      AND B.AccountId = A.AccountId 
    ) 
    AND A.TargetURL LIKE '%/api/v1/cust/details%' 
    AND A.Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
    ORDER BY A.TimeMark DESC 
0

в SQL Server я использую для даты> = Convert (NCHAR (10), first_date_value, 103) ............

-1

Необходимо добавить команду CustomerID и получить записи HAVING COUNT(CustomerID) = 1; Это должно дать вам все записи, где CustomerID является уникальным

SELECT TimeMark, 
    CustomerID, 
    AccountId, 
    TargetURL 
FROM BTILog 
WHERE timemark BETWEEN '20140926 00:00:00' 
     AND '20141020 23:59:59' 
    AND TargetURL LIKE '%/api/v1/cust/details%' 
    AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
ORDER BY TimeMark DESC 
GROUP BY CustomerID 
HAVING COUNT(CustomerID) = 1; 
0

насчет подвыборки, которая подсчитывает строки для текущего CustomerID

SELECT TimeMark, 
     CustomerID, 
     AccountId, 
     TargetURL 
    FROM BTILog ALIAS outer 
    WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
     AND (
       SELECT count(*) 
       FROM BTILog 
       WHERE timemark BETWEEN '20140926 00:00:00' 
       AND '20141020 23:59:59' 
       AND TargetURL LIKE '%/api/v1/cust/details%' 
       AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
       AND outer.CustomerID = CustomerID 
     ) == 1 

    ORDER BY TimeMark DESC 
1

Вы должны использовать группу по и агрегирование функцию TimeMark. Следующие даст вам уникальный идентификационный номер клиента записей с последнего входа метки времени для каждого из них:

SELECT max(TimeMark) TimeMark, 
     CustomerID, 
     AccountId, 
     TargetURL 
    FROM BTILog 
    WHERE timemark BETWEEN '20140926 00:00:00' 
      AND '20141020 23:59:59' 
     AND TargetURL LIKE '%/api/v1/cust/details%' 
     AND Class LIKE 'com.btfin.security.sso.SSODetailsFactory%' 
    GROUP BY CustomerID, AccountId,TargetURL 
    ORDER BY TimeMark DESC 
+0

Это должно сработать для вас, если вы заинтересованы только в последнем знаке time_mark. Если вы хотите, чтобы вы были ранними, вы могли бы, конечно, использовать Min (TimeMark). Это предполагает, что на одного Клиента имеется ровно один счет. В противном случае у вас могут быть дубликаты. Он также предполагает, что у вас не будет нескольких классов, соответствующих вашему условию LIKE. –