SQL查询更新表

时间:2016-11-30 06:28:30

标签: sql

可能是一个愚蠢的例子,但很想知道如何使用SQL查询来做到这一点。我正在使用MySQL但尝试编写查询db独立方式。

我有下表,

Course
---------
Id | lang    | batch | flag
===========================
1  | Java    |  A    | null
2  | Cpp     |  B    | null
3  | Java    |  A    | null
4  | Java    |  C    | null
5  | Java    |  C    | null

查询是,如果为同一批次找到lang = Java的两条记录,则为第一个条目设置flag = 0,为表格中的第二个条目设置flag = 1。

因此上述查询的输出如下所示,

Course
---------
Id | lang    | batch | flag
===========================
1  | Java    |  A    | 0
2  | Cpp     |  B    | null
3  | Java    |  A    | 1
4  | Java    |  C    | 0
5  | Java    |  C    | 1

我如何为上面的例子编写SQL查询。感谢您的帮助:)

编辑: 对于晚期编辑,很抱歉,如果只找到一条lang = java和任何批处理的记录,那么将标志设置为0。 是否可以在单个查询中编写两个查询?

5 个答案:

答案 0 :(得分:2)

假设给定的匹配批次只有两个记录,以下内容应该可以正常工作:

UPDATE Course t1
INNER JOIN
(
    SELECT batch
    FROM Course
    GROUP BY batch
    HAVING SUM(CASE WHEN lang = 'Java' THEN 1 ELSE 0 END) = 2
) t2
    ON t1.batch = t2.batch
INNER JOIN
(
    SELECT batch, MIN(Id) AS minId
    FROM Course
    GROUP BY batch
) t3
    ON t2.batch = t3.batch
SET t1.flag = CASE WHEN t1.Id = t3.minId THEN 0 ELSE 1 END

在这里演示:

SQLFiddle

注意:上面的Fiddle执行SELECT来显示哪些记录将被更新,以及每个记录的旧标志值和新标志值。

您需要使用的确切JOIN语法是特定于数据库的。我给出了MySQL的语法,但是只要它支持连接更新,查询在转到另一个RDBMS(如SQL Server)时不会有太大变化。

答案 1 :(得分:1)

使用CTE创建行号并根据CTE更新物理表:

CREATE TABLE #Course(Id INT,lang VARCHAR(100), batch VARCHAR(10),flag INT)
INSERT INTO #Course(Id ,lang , batch ,flag )
SELECT 1  ,'Java','A'    , NULL UNION ALL
SELECT 2  ,'Cpp','B'    , NULL UNION ALL
SELECT 3  ,'Java','A'    , NULL UNION ALL
SELECT 4  ,'Java','C'    , NULL UNION ALL
SELECT 5  ,'Java','C'    , NULL

;WITH CTE AS
( 
 SELECT ROW_NUMBER() OVER (PARTITION BY batch ORDER BY Id) RNo , lang    
 ,batch,Id FROM #Course
)
UPDATE #Course SET flag = CASE WHEN RNo = 1 THEN 0 ELSE 1 END
FROM CTE 
WHERE #Course.Id = CTE.Id 

SELECT * FROM #Course

答案 2 :(得分:0)

有2个更新:

首先:

update Course set flag = 0 where Id in (select min(id) from Course C where
Lang = 'Java' group by lang, batch);

第二

update Course set flag = 1 where lang = 'Java' and flag is null

答案 3 :(得分:0)

我认为我们可以通过使用CASE和子查询来实现:

update c set c.flag = case when c.id = t.id then 1 else 0 end
from #Course c
inner join (select max(id) id, lang, batch 
            from #Course 
            group by lang, batch having count(id)>1) t on c.lang = t.lang
and t.batch = c.batch

答案 4 :(得分:0)

这是PostgreSQL测试版本:

UPDATE
Course
SET
flag = CASE WHEN t2.min = Course.Id THEN 0 ELSE 1 END
FROM
(SELECT
Course.batch,
MIN(Course.Id)
FROM
Course
WHERE
Course.lang = 'Java'
GROUP BY
Course.batch
HAVING COUNT(Course.batch) = 2) AS t2
WHERE
Course.batch = t2.batch