排除具有分配给不同表中的非唯一字段的字段的结果

时间:2017-11-07 20:42:22

标签: sql sql-server tsql exists

我正在尝试从表(tblRecords)中进行选择,并排除具有在不同表(tblPerson)中重复的值的行。作为一个直观的例子:

当前表:

 tblRecords:                    tblPerson:
+------------+-------------+   +------------+------------+
| CustomerID | OrderID     |   | PersonID   | UserID     |
+------------+-------------+   +------------+------------+
| 101        |           1 |   | 8          | 3004       |
| 18         |           7 |   | 5          | 81         |
| 8          |           1 |   | 19         | 100        |
| 100        |           2 |   | 19         | 101        |
+------------+-------------+   +------------+------------+

期望的输出:

+------------+-------------+
| CustomerID | OrderID     |
+------------+-------------+
| 18         |           7 |
| 8          |           1 |
+------------+-------------+

这是一个简化的例子,请原谅不良桌面设计的迹象。由于PersonID'19'在tblPerson中出现多次,我想排除tblRecords的所有结果,其中CustomerIDUserID相同对应重复的PersonID(因此排除100和101)。

我认为解决方案是在查询的WHERE子句中使用NOT EXISTS,而不是按重复值进行分组。这是我写的查询没有按预期工作:

SELECT *
FROM  tblRecords
WHERE NOT EXISTS (
    SELECT PersonID
    FROM tblPeople
    GROUP BY PersonID
    HAVING COUNT(PersonID) > 1
)

我不明白如何修复查询,因此它知道从tblRecords排除结果CustomerID值出现在PersonID中重复的tblPerson旁边。此时,子查询选择我想要排除的确切值。我只是不知道他们是如何在CustomerID中逻辑搜索的。

1 个答案:

答案 0 :(得分:4)

您可以在 <?php $data = json_decode('[ { "id": 1, "value1": 5, "value2": 10 }, { "id": 2, "value1": 50, "value2": 100 }, { "id": 1, "value1": 1, "value2": 2 }, { "id": 2, "value1": 15, "value2": 20 }, { "id": 3, "value1": 15, "value2": 20 } ]'); //print_r(array_group_by($data,'id')); print_r(array_sum_by($data,'id',['value1','value2'])); //print_r(array_sum(array_column($data,'value1'))); function array_sum_by($array,$group,$keys) { $groupeddata = array_group_by($array,$group); return array_map(function($items) use($group,$keys) { foreach($keys as $key) { $values[$key] = array_sum(array_column($items,$key)); } $first = array_shift($items); if(is_object( $first ) && isset( $first->{ $group } )){ $values = array_merge([ $group => $first->{ $group } ], $values); }elseif(isset($first[$group])){ $values = array_merge([ $group => $first[$group] ], $values); } return $values; },$groupeddata); } function array_group_by( array $array, $key ) { if ( ! is_string( $key ) && ! is_int( $key ) && ! is_float( $key ) && ! is_callable( $key ) ) { trigger_error( 'array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR ); return null; } $func = ( is_callable( $key ) ? $key : null ); $_key = $key; // Load the new array, splitting by the target key $grouped = []; foreach ( $array as $value ) { if ( is_callable( $func ) ) { $key = call_user_func( $func, $value ); } elseif ( is_object( $value ) && isset( $value->{ $_key } ) ) { $key = $value->{ $_key }; } elseif ( isset( $value[ $_key ] ) ) { $key = $value[ $_key ]; } else { continue; } $grouped[ $key ][] = $value; } // Recursively build a nested grouping if more parameters are supplied // Each grouped array value is grouped according to the next sequential key if ( func_num_args() > 2 ) { $args = func_get_args(); foreach ( $grouped as $key => $value ) { $params = array_merge( [ $value ], array_slice( $args, 2, func_num_args() ) ); $grouped[ $key ] = call_user_func_array( 'array_group_by', $params ); } } return $grouped; } 查询的where子句中添加相关性:

not exists()

对于更新的问题,请使用SELECT * FROM ISOW.dbo.tblRecords r WHERE NOT EXISTS ( SELECT PersonID FROM ISOW.dbo.tblPeople p where p.PersonID= r.CustomerID GROUP BY PersonID HAVING COUNT(PersonID) > 1 ) not exists()

exists()

rextester演示:http://rextester.com/DNWK20907

返回:

select r.CustomerID, r.OrderID
from  dbo.tblRecords r
where not exists (
    select PersonID
    from dbo.tblPeople p
    where p.UserID= r.CustomerID 
      and exists (
        select 1
        from dbo.tblPeople i
        where i.PersonID = p.PersonID
          and i.UserID <> p.UserID
      )
    )