在MSSQL IN子句中使用复杂的键

时间:2015-08-25 20:26:34

标签: mysql sql-server

我有以下在MySQL中运行的查询:

SELECT 'DEMO' client, COUNT(*) n, SUM(PYMT_Total_Paid) actual
FROM Payments 
WHERE (PYMT_CLIENT1,PYMT_CLIENT2) IN (('DEMO','SL'))
  AND PYMT_DTEPYD ='20150825' 
  AND PYMT_MISC IN ('PY','RC','ER','RG','SP','BN','BS','SB')
  AND PYMT_BEEN_REVERSED != 'Y'

当我在MSSQL中运行它时,它会失败并显示以下消息:

An expression of non-boolean type specified in a context where a condition
is expected, near ','.

如果我从查询中删除(PYMT_CLIENT1,PYMT_CLIENT2) IN (('DEMO','SL')) AND,它运行正常。因此,当使用IN子句搜索复合键时,MSSQL似乎需要与MySQL不同的语法。

任何关于在何处找到正确语法或正确语法的指针都将受到高度赞赏。 谢谢!

修改

我提供的案例过于简单了。如果查询在IN子句中有多个对,例如,解决方案也应该有效。 ...... IN (('DEMO","SL"),("ED","AUTO"),("ED","PHOTO"))

4 个答案:

答案 0 :(得分:3)

你也可以改变

(PYMT_CLIENT1,PYMT_CLIENT2) IN (('DEMO','SL'))

EXISTS (SELECT PYMT_CLIENT1,PYMT_CLIENT2 INTERSECT SELECT 'DEMO','SL')

这对空值的处理与结合等式谓词不同,但在你的情况下没有区别,因为右边的两个常量不是空的。

答案 1 :(得分:2)

SQL Server不支持Row Value Constructor

类似案例UPDATE tab SET (a,b) = ('Yes', 'No')。 使用T-SQL version

<强>解决方案:

1)当条件简单时使用AND

(PYMT_CLIENT1,PYMT_CLIENT2) IN (('DEMO','SL'))
/* becomes */
PYMT_CLIENT1 = 'DEMO' AND PYMT_CLIENT2 = 'SL'

2)第二种情况IN (('DEMO","SL"),("ED","AUTO"),("ED","PHOTO"))可以解开,如:

  WHERE 
    CASE 
      WHEN PYMT_CLIENT1 = 'DEMO' AND PYMT_CLIENT2 = 'SL'    THEN 1
      WHEN PYMT_CLIENT1 = 'ED'   AND PYMT_CLIENT2 = 'AUTO'  THEN 1
      WHEN PYMT_CLIENT1 = 'ED'   AND PYMT_CLIENT2 = 'PHOTO' THEN 1
      ELSE 0
    END = 1 

2&#39;)将条件从WHERE移动到INNER JOIN并加入Derived Table

SELECT 
    'DEMO'               AS  client,
    COUNT(*)             AS  n,
    SUM(PYMT_Total_Paid) AS actual
FROM Payments p
INNER JOIN (VALUES ('DEMO', 'SL'), ('ED', 'AUTO'), ('ED', 'PHOTO')) AS x(c1, c2)
ON p.PYMT_CLIENT1 = x.c1 AND p.PYMT_CLIENT2 = x.c2
WHERE
   (...)

2&#39;&#39;)将Martin Smith solution与派生表结合起来

WHERE
   EXISTS 
   (
       SELECT PYMT_CLIENT1,PYMT_CLIENT2
       INTERSECT
       SELECT c1, c2 
       FROM (VALUES ('DEMO', 'SL'), ('ED', 'AUTO'), ('ED', 'PHOTO')) AS X(c1, c2)
   )

答案 2 :(得分:0)

修改您的查询有点像

SELECT 'DEMO' as client, 
COUNT(*) as n, 
SUM(PYMT_Total_Paid) as actual 
FROM Payments 
WHERE PYMT_CLIENT1 IN ('DEMO','SL')
AND PYMT_CLIENT2 IN  ('DEMO','SL') 
AND PYMT_DTEPYD = '20150825' 
AND PYMT_MISC IN ('PY','RC','ER','RG','SP','BN','BS','SB') 
AND PYMT_BEEN_REVERSED != 'Y';

答案 3 :(得分:0)

这是正确的逻辑:

WHERE PYMT_CLIENT1 = 'DEMO' AND PYMT_CLIENT2 = 'SL' AND
      PYMT_DTEPYD = '20150825' AND
      PYMT_MISC IN ('PY', 'RC', 'ER', 'RG', 'SP', 'BN', 'BS', 'SB') AND 
      PYMT_BEEN_REVERSED <> 'Y';

表达式(a, b) in ((x, y))正在查看值的,而不是单独查看每个值。因为IN列表中只有一个值,所以这相当于单独进行比较。