SQL语句中的IN运算符不起作用?
在SQLServer中,我有一个表MyTable,它有以下3列:Pbigint、Fbigint、Dbigint 现在我需要做的是将所有记录按相同的p值分组,然后在每组中计算以下值:SQL语句中的IN运算符不起作用?,sql,sql-server,Sql,Sql Server,在SQLServer中,我有一个表MyTable,它有以下3列:Pbigint、Fbigint、Dbigint 现在我需要做的是将所有记录按相同的p值分组,然后在每组中计算以下值: V = ABS((P & 0xFFFFFFFF) * 256 - F) 并删除组中的所有记录,最小值为V的记录除外 因此,我编写SQL语句如下: DELETE FROM MyTable WHERE (P, ABS((P & 0xFFFFFFFF) * 256 - F)) NOT IN (SELECT
V = ABS((P & 0xFFFFFFFF) * 256 - F)
并删除组中的所有记录,最小值为V的记录除外
因此,我编写SQL语句如下:
DELETE FROM MyTable WHERE (P, ABS((P & 0xFFFFFFFF) * 256 - F)) NOT IN (SELECT P, MIN(ABS((P & 0xFFFFFFFF) * 256 - F)) FROM MyTable GROUP BY P HAVING COUNT(*) > 1)
但在SQL Server中,我将得到以下错误:
Msg 4145 SQL Server An expression of non-boolean type specified in a context where a condition is expected,near ','
为什么??另外,按位and&是否在SQLServer2005中工作?我只有SQL Server 2008 R2,而位于的在线文档没有说明它是否支持2005和2008
更新1
P、 F,D都是bigint类型
更新2
在其他人的帮助下,我终于用notexists编写了一个查询,如下所示:
DELETE FROM MyTable WHERE (P, ABS((P & 0xFFFFFFFF) * 256 - F)) NOT IN (SELECT P, MIN(ABS((P & 0xFFFFFFFF) * 256 - F)) FROM MyTable GROUP BY P HAVING COUNT(*) > 1)
方法1:从不存在的MyTable t中删除t,从SELECT p中选择1,MINABSP&0xFFFFFFFF*256-F作为minpf
通过P tt从MyTable组开始,其中tt.P=t.P,tt.minpf=abs.P&0xFFFFFFFF*256-t.F
注意:我删除HAVE COUNT*>1,否则,该语句还将删除组中只有一条记录的记录
虽然它有效,但我怀疑它的性能。由于在大多数组中按P分组,因此只有一条记录,而在这样一个组中计算minpf,然后删除具有计算值minpf的记录是在浪费时间,在这样一个组中不会删除任何记录。所以,只是想知道是否有更好的方法来做同样的事情
更新3
我用Gordon提供的两种方法测试了methodmethod 1的性能,只做了少量修改
方法2:
删除t
从MyT表左联接
选择P、MINABSP和0xFFFFFFFF*256-F作为最小功率因数
从MyTable
P分组
tt
在tt.p=t.p和tt.minpf=tt.p&0xFFFFFFFF*256-tt.F上
其中tt.P为空
方法3:
从选择t.*中删除t,
按P顺序按ABSP分区上的行数&0xFFFFFFFF*256-F作为seqnum
来自MyT表
T
其中seqnum>1
性能数据如下:
第一次测试:
22721行受影响
方法1:16094
22721行受影响
方法2:17156
22721行受影响
方法3:12188
第二次测试:
22721行受影响
方法1:26297
22721行受影响
方法2:27562
22721行受影响
方法3:11625
第三次测试:
22721行受影响
方法1:26297
22721行受影响
方法2:27359
22721行受影响
方法3:11578
因此,根据测试,方法3的性能最好。IN语句确实有效,但它们的工作方式与您使用它们的方式不同-就像这样简单。中的内容是比较值列表,而不是另一条sql语句 在您的情况下,您不在-您确实使用join删除表单select,并使用它定义要删除的行。在In之后的select查询必须只返回一列,请先测试它。尝试以下操作:
DELETE FROM MyTable
WHERE concat(P, ABS((P & 0xFFFFFFFF) * 256 - F)) NOT IN (SELECT concat( P, MIN(ABS((P &
0xFFFFFFFF) * 256 - F))) FROM MyTable GROUP BY P HAVING COUNT(*) > 1)
在SQL Server中,只需使用联接: 或者,更简单地使用窗口函数:
DELETE t
FROM (SELECT t.*,
ROW_NUMBER(*) OVER (PARTITION BY P ORDER BY ABS((P & 0xFFFFFFFF) * 256 - F) as seqnum
FROM MyTable t
) t
WHERE seqnum > 1;
改为使用NOT EXISTS。同意@jarlh对NOT EXISTS的看法。NOT IN具有意外值,如果您知道它使用空值执行它的行为,则这是意料之中的。例如选择1,其中1不在从值2,3中选择N,为空VN;将不返回任何值,尽管1不在子查询中。@非常感谢。我只是用notexists重写了这个查询,它很复杂,我怀疑它的性能不够好。你有什么好的建议吗?在SQL标准中,有一个多列,比如a,b在选择x,y中。。允许-但SQL Server在此中不支持。中的内容是比较值列表,而不是其他SQL语句。那是错误的。其中id在“选择x自…”中。。这是完全正确的。在标准SQL中,如果选择x,y..中的a,b,则问题的查询也将有效,但是SQL Server不支持这一点。非常感谢。但是,如果groupgroup by P中只有一条记录,则第一个查询将删除这些记录,这是不需要的。第二个查询似乎错过了一个正确的选项。删除计数*>1可以解决问题,但可能会大大降低性能?@alancc。如果希望每个组保留一行,则第二个查询应具有行号。您的伪代码使用COUNT*表示您希望删除所有包含1个以上成员的组,但我看到文本中更清楚地说明了您希望执行的操作。非常感谢。对于具有多个成员的所有组,我将保留具有最小值的成员,并删除所有剩余的成员。此外,我的第一个查询中的HAVING COUNT*>1是不正确的,因为不在将导致它排除只有一个成员的组。很抱歉,SQL Server 2008 R2中似乎没有联系人功能