我知道使用联接如何创建重复值。因此,我们需要在联接语句中使用DISTINCT关键字。但是,为什么使用子查询也不会给出重复的值?考虑以下对产生相同结果的T-SQL语句
子查询
import { Component, OnInit } from '@angular/core';
import { Controls } from '../main/main.component';
@Component({
selector: 'app-generator',
templateUrl: './generator.component.html',
styleUrls: ['./generator.component.scss']
})
export class GeneratorComponent implements OnInit {
constructor() { }
ngOnInit() {
}
/**
* name
*/
public generateNewControl(controlType:string):string {
console.log('new control generated');
switch(controlType){
case 'text':
return this.renderTextBox();
break;
}
}
renderTextBox():string{
return '<mat-form-field class="example-full-width"><input matInput
placeholder="Favorite food" value="Sushi"></mat-form-field>'
}
generateTextBox():void{
var d = document.getElementById('main');
d.insertAdjacentHTML('beforeend',
this.generator.generateNewControl('text'));
}
}
加入
select ID, Name, Description
from tblProducts
where ID IN
(
Select ProductId from tblProductSales
)
我们必须对表联接使用distinct关键字,但对于子查询则不能使用。我不明白为什么会这样
答案 0 :(得分:0)
在第一个查询上,您扫描产品表并检查该产品是否有任何销售。之所以这样,是因为每种产品仅出现一次,没有重复。 IN
是布尔运算符,因此,即使子查询返回重复结果,也仅在与这些值中的任何一个匹配时才返回一行。
在第二个查询中,将每个产品与ID相匹配的任何销售合并。之所以这样,是因为同一产品有多次销售,因此您会重复购买。
在两个表之间加入一个笛卡尔积。
示例:
Pruducts Sales
1 1
2 1
3 2
2
2
第一个查询返回(1,2)
第二条查询返回(1,1,2,2,2)
,因为产品中的每一行都试图与销售中的一行相匹配
答案 1 :(得分:0)
您误解了WHERE
和JOIN
。
由于非常简单的原因,第一个查询不会产生重复的结果。 WHERE
子句从结果集中过滤掉行或将其保留在里面。仅此而已。由于WHERE
条件,行不可能“相乘”。
从概念上讲,您可以将WHERE
处理为:
FROM
子句生成的行。WHERE
子句中应用条件。 JOIN
完全是另一种野兽。它是FROM
子句中的 operator ,它组合了两个表/派生表。可以删除行(当JOIN
条件不等于TRUE时)。行可以相乘(如果有多个匹配项)。
顺便说一句,第一种方法比第二种方法要好得多。 SELECT DISTINCT
会产生开销-即使所有行都已经不同。第二种方法不需要这样做。
我通常建议使用EXISTS
编写此逻辑:
select p.ID, p.Name, p.Description
from tblProducts p
where exists (select 1
from tblProductSales ps
where ps.ProductId = p.ID
);
我发现EXISTS
通常更易于优化,并且NOT EXISTS
比NOT IN
更可取,因为NOT EXISTS
处理NULL
的值符合您的期望(但是那是另一个主题)。