Изменение подзапроса для присоединения для обновления таблицы - PullRequest
0 голосов
/ 27 сентября 2019

Я пытался преобразовать подзапрос, чтобы присоединиться к оператору обновления, чтобы продолжить его настройку, чтобы предотвратить тупик.Я тщетно пытался прийти к точному обновлению, так как мне нужно взять Top 1.

- создать ассоциативную таблицу и вставить пример данных

CREATE TABLE [dbo].[Associate](
    [pre_plan_id] [smallint] NULL,
    [pre_type_id] [smallint] NULL,
    [associate_id] [smallint] NOT NULL,
    [deleted] [bit] NOT NULL
)  

INSERT INTO Associate 
VALUES 
(NULL,  NULL,   -32768, 0),
(NULL,  NULL,   2,  1),
(NULL,  NULL,   3,  0)  

- создать таблицу посещенийи вставьте пример данных

CREATE TABLE [dbo].[Visit](
    [type_id] [smallint] NOT NULL,
    [plan_id] [smallint] NOT NULL,
    [associate_id] [smallint] NOT NULL,
    [time_in] [smalldatetime] NOT NULL
) 
INSERT INTO Visit 
VALUES
(390,   31, 3109,   '2009-09-02'),
(304,   32, 3109,   '2010-02-05'),
(388,   31, 3109,   '2010-09-24') 

--- оператор обновления

UPDATE Associate SET pre_plan_id = 
      (SELECT TOP 1 plan_id 
         FROM Visit  
        WHERE associate_id = Associate.associate_id 
          AND time_in > 90
        GROUP BY plan_id 
        ORDER BY Count(*) DESC)
 WHERE deleted = 0

Может кто-нибудь помочь мне с этим?Спасибо!

1 Ответ

2 голосов
/ 27 сентября 2019

Дайте этому попытку:

UPDATE a 
SET a.pre_plan_id = z.plan_id
FROM
  associate a
  INNER JOIN
  (
    SELECT associate_id, plan_id 
    FROM
    (
      SELECT associate_id, plan_id, ROW_NUMBER() OVER(PARTITION BY associate_id ORDER BY ctr DESC) rown
      FROM (SELECT associate_id, plan_id, count(*) as ctr FROM visit WHERE time_in > 90 GROUP BY associate_id, plan_id) x
    ) y
    WHERE rown = 1
  ) z
  ON z.associate_id = a.associate_id
WHERE deleted = 0

У него есть 3 подзапроса только потому, что я не могу вспомнить, возможно ли использовать сгруппированный счетчик (*) в оконной функции. Если это так,это может работать:

UPDATE a 
SET a.pre_plan_id = z.plan_id
FROM
  associate a
  INNER JOIN
  (
    SELECT associate_id, plan_id 
    FROM
    (
      SELECT associate_id, plan_id, ROW_NUMBER() OVER(PARTITION BY associate_id ORDER BY COUNT(*) DESC) rown
      FROM visit 
      WHERE time_in > 90 
      GROUP BY associate_id, plan_id
    ) y
    WHERE rown = 1
  ) z
  ON z.associate_id = a.associate_id
WHERE deleted = 0

Или даже это, более короткая форма:

UPDATE a 
SET a.pre_plan_id = z.plan_id
FROM
  associate a
  INNER JOIN
  (
      SELECT associate_id, plan_id, ROW_NUMBER() OVER(PARTITION BY associate_id ORDER BY COUNT(*) DESC) rown
      FROM visit 
      WHERE time_in > 90 
      GROUP BY associate_id, plan_id
  ) z
  ON z.associate_id = a.associate_id AND z.rown = 1
WHERE deleted = 0

Кажется, вы хотите подсчитать посещения и выбрать ту, которая имеет наибольшее количество вхождений plan_idи затем используйте это, чтобы заполнить pre_plan_id.Сгруппировав и получив подсчет, затем выполнив row_number () по убыванию отсчетов, это означает, что наибольшим отсчетом будет 1, который мы можем отфильтровать и вытащить связанный plan_id как pre_plan_id

...