CTE вместо курсора - PullRequest
       1

CTE вместо курсора

0 голосов
/ 30 июня 2011

Может ли кто-нибудь указать мне на пример использования CTE для перехода по набору записей вместо курсора?

Все примеры, которые мне удалось найти, показывают рекурсию. Мне это не нужно. Я просто хочу пройти через набор записей по одному.

Спасибо.

(EDIT)

Возможно, это лучше задать другим способом. Я предположил, что CTE или курсор могут быть лучшим способом получить нужные мне данные, но вот пример.

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

2011-05-24 11:06:28.080     CODE1   199 
2011-05-24 11:06:28.080     CODE2   199 
2011-06-08 13:30:14.830     CODE2   209 
2011-06-08 13:30:14.313     CODE1   209 
2011-06-08 13:30:13.840     CODE2   209 
2011-06-08 13:30:13.450     CODE1   209 
2011-06-08 13:30:13.050     CODE2   209 
2010-05-07 10:45:06.800     CODE3   79  
2010-05-07 10:45:04.833     CODE3   79  
2010-10-15 07:30:16.193     CODE3   79  
2010-01-26 13:51:43.923     CODE3   79  
2010-01-26 13:51:43.923     CODE3   79  
2010-01-26 13:51:44.427     CODE3   79  
2010-01-26 13:51:45.103     CODE3   79  
2010-01-26 13:51:45.890     CODE3   79  
2010-01-26 13:51:46.733     CODE3   79  
2010-01-25 12:40:39.737     CODE3   81  
2010-01-25 12:40:40.890     CODE3   81  
2010-01-25 12:40:41.627     CODE3   81  
2010-01-25 12:40:43.277     CODE3   81  
2010-01-25 14:29:08.360     CODE3   81  
2010-01-21 19:36:34.660     CODE3   98  
2010-01-21 19:36:34.843     CODE3   98  
2010-01-21 19:36:35.013     CODE3   98  
2010-01-21 22:27:24.317     CODE3   83  
2010-01-21 22:31:21.443     CODE2   83  
2010-01-22 19:44:28.880     CODE3   83  

И я хочу выбрать из этой таблицы самую старую дату и код для каждого пользователя. Можно ли это сделать с помощью CTE?

Я могу сделать выбор, где я группируюсь по customerid и получаю MIN (поле даты), но я не могу получить код, связанный с этой самой ранней датой, если я не добавлю его в мою группу по выражению ... и затем, конечно, Я получаю несколько строк для клиента, по одной с каждым связанным кодом.

Я нашел решение, которое работает, где я создаю временную таблицу и заполняю ее MIN (Дата) и идентификатором клиента, группируя по customerid. Затем я обновляю эту временную таблицу, присоединяя ее к исходной таблице по клиенту и полю даты, чтобы получить код, связанный с этой строкой ... но это похоже на хак.

Мне было интересно, будет ли циклический просмотр исходной таблицы (отсортированной по customerid и дате) и каждый раз, когда я вижу, как новый идентификатор клиента, вставляющий эту запись во временную таблицу, будет более чистым решением ... тем более, что решение, которое я ' m находка предполагает уникальную комбинацию дата / время.

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

  DECLARE @Table1 TABLE 
(
    ClaimDate datetime, 
    VenueCode nvarchar(50), 
    CustomerID int
)
 INSERT INTO @Table1
  SELECT sc.CreateDate, v.code, sc.CSFCustomerID 
  FROM foo join foo1 on (snip)


DECLARE @Table2 TABLE
  ( 
  ClaimDate datetime,
  VenueCode nvarchar(50),
  CustomerID int)



 INSERT INTO @Table2
  select MIN(ClaimDate), NULL, CustomerID from @Table1 group by CustomerID

  UPDATE ft
  SET ft.SomeCode = t.VenueCode
FROM @Table2 ft
INNER JOIN @Table1 t ON ft.CustomerID = t.CustomerID
AND ft.ClaimDate = t.ClaimDate

Спасибо, и я обещаю, что буду лучше выбирать ответы в будущем.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2012

Хотя это довольно старый пост и заголовок вопроса не подходит для иллюстрации вашей основной задачи, это, наконец, И я хочу выбрать из этой таблицы самую старую дату и код для каждого пользователя, которые можно сделатьэто с помощью CTE?

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

-- CTE version of the SQL
WITH CTE (OldestClaimData, CustomerID)
AS
(
  SELECT
    MIN(ClaimDate), CustomerID
  FROM
    UserClaims
  GROUP BY
    CustomerID
)
SELECT DISTINCT
  UC.*
FROM
  UserClaims UC
INNER JOIN
  CTE ON (
    CTE.OldestClaimData=UC.ClaimDate
    AND
    CTE.CustomerID=UC.CustomerID
    AND 
    UC.VenueCode=(
      SELECT TOP 1
        VenueCode
      FROM
        UserClaims sub
      WHERE
        sub.ClaimDate=UC.ClaimDate
        AND
        sub.CustomerID=UC.CustomerID
    )
)
ORDER BY
    UC.CustomerID;

Я поместил мой и ваш код в SQL Fiddle для вашего удобства.

PD работайте над своим примите курс .

0 голосов
/ 30 июня 2011
with qry
(
SELECT Min(Date), userID
FROM TABLE
GROUP BY UserID
)

SELECT Table.*
FROM TABLE 
INNER JOIN qry on qry.UserID = Table.UserID AND qry.Date = Table.Date
...