Reputation: 420
I was trying to convert the subquery to join in the update statement in order to pursuit of tuning it so as to prevent a deadlock. I was trying in vain to come to the exact update as I've to take the Top 1.
-- create associate table and insert sample data
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 visit table and insert sample data
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')
--- the update statement
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
Can anyone help me with this? Thanks!
Upvotes: 0
Views: 58
Reputation: 74625
Give this one a try:
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
It's got 3 subqueries only because I can't remember if it's possible to use a grouped count(*) in a window function.. If it is, this may work:
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
Or even this, shorter form:
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
It seems you want to count up the visits and select the one with the highest number of occurrences of plan_id and then use this to populate pre_plan_id. By grouping and getting the counts, then doing a row_number() over the counts descending it means the highest count will be 1, which we can filter on and pluck out the associated plan_id as the pre_plan_id
Upvotes: 2