【问题标题】:How to manipulate values and get a new result on in SQL?如何在 SQL 中操作值并获得新结果?
【发布时间】:2016-09-20 22:20:15
【问题描述】:

我有这个问题:

SELECT 
    c.ID, c.Firstname, c.lastname, c.BDaY, c.gender, 
    cp.code, cp.Citizenship, r.race, e.ethnicity 
FROM 
    Client AS C (nolock) 
JOIN
    Citizenship AS cp (nolock) ON c.ID = cp.client_ID
JOIN
    Race AS r (nolock) ON c.ID = R.Client_ID 
JOIN 
    Ethnicity AS E (nolock) ON E.Client_ID = c.ID

此查询将返回一些重复的客户姓名,因为他们有不同的种族和民族。

例子:

    ID |FirstName|Lastname|  BDay    | gender | code |citizenship|    race    |    ethnicity 
    1   Pedram    Salamati 01-20-1998    M      1     US citizen   Middle-east     Spanish
    1   Pedram    Salamati 01-20-1998    M      1     US Citizen   Middle-east     unknown
    1   Pedram    Salamati 01-20-1998    M      1     US Citizen   Middle-east     Brazilian
    2   Jesse     Albert   03-05-1982    F      1     US Citizen   African         not Spanish
    2   Jesse     Albert   03-05-1982    F      1     US Citizen   American        not Spanish

我想知道是否有任何方法可以说如果种族不是 = 种族应该是多种族,如果种族不是 = 彼此相同的 ID,请选择最后更新的那个。

PS.Ethnicity 有时间戳,我可以使用Max(e.LastUpdate)

我认为子查询可能会有所帮助!

任何帮助或想法将不胜感激!

【问题讨论】:

  • 您的 Select 语句在表之间没有关系。请使用该信息更新您的帖子。
  • Yuuuupppsssss!对于那个很抱歉!谢谢!
  • 拥有ID 列有什么意义?
  • 要知道哪个ID属于谁以及发生什么类型的更新!
  • 这里有一个相关的问题:stackoverflow.com/q/39236684/5089204

标签: sql sql-server subquery subquery-factoring


【解决方案1】:

这里有一些测试数据来模拟您的环境,您应该将所涉及的表和测试数据分开。包括 DML 语句也是适当且有用的,因此人们可以在回答之前尝试他们的解决方案。

DECLARE @Client AS TABLE (ID INT, Firstname VARCHAR(25), LastName VARCHAR(25), BDay DATE, Gender CHAR(1))
INSERT INTO @Client VALUES (1,'Pedram','Salamati','01-20-1998','M')
,(2,'Jesse','Albert','03-05-1982','F')
DECLARE @Citizenship AS TABLE (Client_ID INT, Code INT, Citizenship VARCHAR(100))
INSERT INTO @Citizenship VALUES (1,1,'US citizen'),(2,1,'US citizen')
DECLARE @Ethnicity AS TABLE (Client_ID INT, Ethnicity VARCHAR(50))
INSERT INTO @Ethnicity VALUES (1,'Spanish'),(1,'unknown'),(1,'Brazilian'),(2,'not Spanish')
DECLARE @Race AS TABLE (Client_Id INT, Race VARCHAR(50), LastUpdate DATETIME)
INSERT INTO @Race VALUES (1,'Middle-east',GETDATE()),(2,'African',GETDATE()),(2,'American',GETDATE() -1)

使用这些变量,您可以执行以下操作,当然有不止一种方式,这只是我选择的一种方式,原因如下:

;WITH cteEthnicity AS (
    SELECT
       e.Client_ID
       ,CASE WHEN COUNT(DISTINCT e.Ethnicity) > 1 THEN 'Multiracial' ELSE MIN(e.Ethnicity) END as Ethnicity
    FROM
       @Ethnicity e
    GROUP BY
       e.Client_ID
)

, cteRace AS (
    SELECT
       r.Client_Id
       ,r.Race
       ,ROW_NUMBER() OVER (PARTITION BY r.Client_Id ORDER BY r.LastUpdate DESC) as RowNumber
    FROM
       @Race r
)

SELECT
    c.ID
    ,c.Firstname
    ,c.lastname
    ,c.BDaY
    ,c.gender
    ,cp.code
    ,cp.Citizenship
    ,r.race
    ,e.ethnicity
From
    @Client AS C --(nolock) 
    Join @Citizenship as cp --(nolock)
    on  c.ID = cp.client_ID
    Join cteRace as r --(nolock)
    ON c.ID = R.Client_ID
    AND r.RowNumber = 1
    Join cteEthnicity as E --(nolock)
    ON E.Client_ID = c.ID

您展示了 2 期 1 与种族和 1 与种族

  • 对于种族:您希望使用聚合来确定要分配的种族。这也可以通过窗口函数来完成,但我在此处编写它的方式将说明即使在 Ethnicity 表中也存在重复项。

  • 对于 Race:您只需要将最新的行按客户端分区,您可以使用 ROW_NUMBER() 函数生成它,然后在连接语句中选择它等于 1 的位置

您没有指出但在某些国家/地区可能存在的第三个问题是双重公民身份。在这种情况下,您可以使用类似于 Race 的方法。

请注意,即使使用了公用表表达式 [CTE],您实际上也可以将它们嵌套为子选择。

【讨论】:

  • 这是伟大的马特!我真的很感谢你的精彩解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-25
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多