从sql数据集中删除重复的address_id

时间:2016-08-08 15:35:10

标签: sql sql-server sql-server-2008

我需要在结果中只获得不同的address_id而不重复。这是我的查询。

    try {
        foreach ($users as $key => $user) {
            DB::table('users')->insert(
                [
                    'name' => $user->user_name,
                    'email' => $user->user_email,
                ]
            );
        }

    } catch (\Exception $e) {
        //something
    }

这是查询的结果 Query result with error in data

我试过分组并使用带有address_id的聚合函数,但我也有非聚合列,所以它对我不起作用。 之后我也尝试使用OVER(address by address.address_id),但它也没有用。

任何帮助都将提前得到赞赏。

谢谢

**业务逻辑/要求的更新**

我需要为学生家长提供独特的地址。由于父母可以有两个或更多的孩子住在同一地址,因此会导致重复。换句话说,我每个父母只需要一个孩子。

1 个答案:

答案 0 :(得分:0)

从结果图片看,classifctn列的值超过1,因此重复行。为了得到1个不同的address_id,其余的列要么从查询中删除它,要么你可以设置一个优先级,每个address_id只返回1个记录

请进一步标记您实际使用的RDBM。例如,MySQL没有窗口函数,但是你使用OVER标记了它(分区....这在mysql中是不可能的

;WITH cte (
    SELECT DISTINCT address.address_id, address.address1, address.streetcity, state.stateabbrev, rtrim(ltrim(case when address.streetzipcode is not null and address.streetzipcode != 'NULL' then address.streetzipcode else '' end))+case when len(address.streetzipplus4)>0 then '-'+rtrim(ltrim(address.streetzipplus4)) else '' end as streetzipcode, address.homephone,
          dbo.f_addressstudent (student.address_id) as Students, 
          dbo.f_addresspeople (student.address_id) as Adults,
          case 
             when @classif_id IS NULL then 0 
             else 
             student.classif_id 
          end classif,
          classifctn,

          ROW_NUMBER() OVER (PARTITION BY address.address_id ORDER BY HOW WILL YOU CHOOSE?) AS RowNum

       FROM district WITH(NOLOCK) 
          JOIN dbo.building ON building.district_id = district.district_id 
          JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id
          JOIN dbo.student WITH(NOLOCK) ON student.student_id = studbldg_bridge.student_id
          JOIN classif with(nolock) on student.classif_id = classif.classif_id
          LEFT JOIN dbo.address WITH(NOLOCK) ON student.address_id = address.address_id 
          LEFT JOIN dbo.state WITH(NOLOCK) ON address.streetstate_id = state.state_id
          LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id
       WHERE district.district_id = (SELECT district_id FROM dbo.building WITH(NOLOCK) WHERE bldg_id = @bldg_id)
)

SELECT *
FROM
    cte
WHERE
    RowNum = 1
ORDER BY
    classif
    ,Adults
    ,Students

或者,您可以嵌套您的选择查询。请注意,虽然这个解决方案有点无用,因为如果您真的不关心该列,它只会返回1级/ classifctn,如果您真的不关心该列,那么您应该从查询中删除它。

实际上,当多个学生位于同一地址时,您的classifctn和classif列都会导致多行。这是一种将这些值连接到单个行的方法。您应该花更多时间在您的业务案例上并为我们定义它。但是这里有一个例子:

SELECT DISTINCT
    address.address_id
    ,address.address1
    ,address.streetcity
    ,state.stateabbrev
    ,LTRIM(RTRIM(ISNULL(NULLIF(address.streetzipcode,'NULL'),'')))
       + CASE WHEN LEN(address.streetzipplus4) > 0 THEN '-' ELSE '' END
       + LTRIM(RTRIM(ISNULL(address.streetzipplus4,''))) AS streetzipcode
    ,address.homephone
    ,dbo.f_addressstudent (student.address_id) as Students
    ,dbo.f_addresspeople (student.address_id) as Adults
    , case 
       when @classif_id IS NULL then 0 
       else student.classif_id 
      end classif

        ,STUFF(
        (SELECT ',' + CAST(classif_id AS VARCHAR(100))
        FROM
            classif c
        WHERE c.classif = student.classif
        FOR XML PATH(''))
        ,1,1,'') AS classifs

        ,STUFF(
        (SELECT ',' + CAST(classifctn AS VARCHAR(100))
        FROM
            classif c
        WHERE c.classif = student.classif
        FOR XML PATH(''))
        ,1,1,'') AS classifctns
FROM
    district WITH(NOLOCK) 
    INNER JOIN dbo.building
    ON building.district_id = district.district_id
    AND building.bldg_id = @bldg_id
    INNER JOIN dbo.student WITH(NOLOCK)
    ON student.student_id = studbldg_bridge.student_id
    INNER JOIN dbo.address WITH(NOLOCK)
    ON student.address_id = address.address_id 
    LEFT JOIN dbo.state WITH(NOLOCK)
    ON address.streetstate_id = state.state_id

注意我提前并更改了邮政编码逻辑,以向您展示ISNULL()NULLIF()在某些情况下有用的情况。我还删除了3个表,因为2个未使用,第三个最终用于子选择以连接值。地址表也被更改为INNER JOIN,因为如果地址不存在,则所有其他信息都变为空白/无用....

INNER JOIN dbo.studbldg_bridge WITH(NOLOCK) ON studbldg_bridge.bldg_id=building.bldg_id    
    LEFT JOIN dbo.state AS mailstate WITH(NOLOCK) ON address.state_id = mailstate.state_id
    INNER JOIN classif with(nolock) on student.classif_id = classif.classif_id