SQL - Update a field if all in group are the same
我有一个SQL Server 2014临时表#SourceTable如下所示,其中AllTheSamePerDOI是一个位字段,默认为0:
1 2 3 4 5 6 7 8 | ID | DOI | Affiliations | SameAffiliationsPerDOI ----+-----+--------------+----------------------- 1 | 1 | Text A | 0 2 | 1 | Text A | 0 3 | 7 | Text CCC | 0 4 | 7 | Text CR | 0 5 | 7 | Text CCC | 0 6 | 9 | Text CCC | 0 |
仅当同一DOI中的所有记录在该分组中的所有关系中具有完全相同的文本时,我才想将SameAffiliationsPerDOI字段设置为1。因此最终结果看起来像这样,其中DOI 1和DOI 9都具有1集,因为每个DOI中的所有东西对于其所有记录在关联中都具有相同的值。如何编写SQL语句来做到这一点?
1 2 3 4 5 6 7 8 | ID | DOI | Affiliations | SameAffiliationsPerDOI ----+-----+--------------+----------------------- 1 | 1 | Text A | 1 2 | 1 | Text A | 1 3 | 7 | Text CCC | 0 4 | 7 | Text CR | 0 5 | 7 | Text CCC | 0 6 | 9 | Text CCC | 1 |
我喜欢使用可更新的CTE和窗口函数来解决这些问题:
1 2 3 4 5 6 7 8 9 | WITH toupdate AS ( SELECT st.*, MIN(Affiliations) OVER (partition BY doi) AS mina, MAX(Affiliations) OVER (partition BY doi) AS maxa FROM #SourceTable st ) UPDATE toupdate SET SameAffiliationsPerDOI = 1 WHERE mina = maxa; |
您也可以使用
编写此代码
1 2 3 4 5 6 | UPDATE #SourceTable st SET SameAffiliationsPerDOI = 1 WHERE NOT EXISTS (SELECT 1 FROM #SourceTable st2 WHERE st2.doi = st.doi AND st2.Affiliations <> st.Affiliations ); |
哪个更快可能取决于数据中值的分布和可用索引。
因此,据我了解,这是一次更新吗?对于类似的未来案例,不是连续更新吗?
如果是这样,请尝试以下SQL代码:
1 2 3 | UPDATE #SourceTable SET SameAffiliationsPerDOI = 1 WHERE ID IN (1, 2, 6); |
希望有帮助。
如果要使其自动化,则可能必须调查触发器。
1 2 3 4 | UPDATE S SET SameAffiliationsPerDOI = 1 FROM #SourceTable S WHERE NOT EXISTS (SELECT 1 FROM #SourceTable S2 WHERE S2.DOI = S.DOI AND S2.Affiliations <> S.Affiliations) |
以下是使用density_rank()窗口函数的解决方案:
1 2 3 4 5 6 7 | WITH ranked AS ( SELECT DOI, dense_rank() OVER (partition BY DOI ORDER BY Affiliations) r FROM #SourceTable), same AS (SELECT DOI FROM ranked GROUP BY DOI HAVING MAX(r)=1) UPDATE #SourceTable SET SameAffiliationsPerDIO=1 WHERE DOI IN (SELECT DOI FROM same) |