MySQL存储过程:WHERE中的IF

3

我正在尝试以以下方式选择一些数据:

SELECT column
FROM table
WHERE a = a1
AND (b = b1 OR b = b2 OR b = b3);

我希望它能做的是如果b不等于b1,检查b是否等于b2。但是,如果b=b1,则不要检查其他条件。 这个选择语句的结果必须只有一个条目。但是,在我没有的语句中,它检查所有三个条件,并且有时返回多行。同样,如果条件为真,我希望它停止检查。
您有任何实现这个的想法吗?我尝试了case但并没有成功......
预先感谢!
编辑 这是我正在尝试运行的实际查询。
INSERT INTO shipment_flights 
    (airlinename, flt_no, flt_date, destination, phone, depttime, arrivaltime, pcs, weight)
SELECT st.airlinename, flightno, flightdate, destination,     
(SELECT phone 
FROM carrierlocations 
WHERE carriers_carrierid = (select carrierid from carriers where airlinename = st.airlinename) 
AND (city = destination OR (city != destination AND
    city = (SELECT city FROM airports WHERE iataid = 
            (SELECT airports_iataid FROM ratelegs 
                WHERE shipments_shipid = c.shipments_shipid))
                ))) phone, 
depttime, arrivaltime, sum(linepcs), sum(lineweight)
FROM segment_times st
    JOIN contents2flights c2f 
        ON st.flightid = c2f.segments_flights_flightid 
        AND st.segmentid = c2f.segments_segmentid 
    JOIN contents c 
        ON c.lineno = c2f.contents_lineno 
        AND c.shipments_shipid = c2f.contents_shipments_shipid

WHERE c.shipments_shipid = var_shipid
GROUP BY flightid
ORDER BY flightdate, depttime;

这是一个样例输出:
airlinename         flt_no  flt_date        destination    phone         pcs   weight
Everts Air Alaska   CH1     2008-02-20      Hughes         9074502351    24    2121

这个查询将大量航班数据插入临时表。我遇到的问题是获取位置的电话号码。具体代码如下:

(SELECT phone 
FROM carrierlocations 
WHERE carriers_carrierid = (select carrierid from carriers where airlinename = st.airlinename) 
AND (city = destination OR (city != destination AND
    city = (SELECT city FROM airports WHERE iataid = 
            (SELECT airports_iataid FROM ratelegs 
                WHERE shipments_shipid = c.shipments_shipid))))) phone

在Amit Bhargava建议的查询中,只有临时表中有一行时才会得到正确的结果。如果有更多的行,则在选择电话部分会抛出错误。
"错误代码:1242。子查询返回多个行"

请您能否提供一些样本数据/输出? - Chetter Hummin
2个回答

3
通过使用IF()+IF()+IF(),并测试总和=1可以避免很多额外的和不符合其他标准的情况。如果2个或所有3个相同,则求和将大于1。如果它们都不匹配,则结果为0。这应该正好符合您的要求。
SELECT column
  FROM table
  WHERE a = a1
    AND  if( b = b1, 1, 0 )
       + if( b = b2, 1, 0 )
       + if( b = b3, 1, 0 ) = 1

或者……在ypercube的帮助下,我经常忘记逻辑测试返回真/假分别为1或0,例如...

SELECT column
  FROM table
  WHERE a = a1
    AND  (b = b1) + (b = b2) + (b = b3) = 1

@zanlok:你甚至可以这样写:WHERE a = a1 AND (b=b1)+(b=b2)+(b=b3) = 1 - ypercubeᵀᴹ
@ypercube,感谢您的替代方案...我总是忘记逻辑返回1与0。对于具有布尔真/假历史的情况,忘记1/0也是可行的。 - DRapp
那么,如果总和大于1,它如何确定我需要使用第一条语句? - Nikita Silverstruk
1
@Nikita,你的意思是只要有一个条件为真就可以了,不多也不少。如果是0+0+0,那就不行;1+1+0也不行;1+0+1也不行;0+1+1也不行。但是1+0+0可以,0+1+0也可以,0+0+1也可以。 - DRapp

1
请尝试以下方法。虽然不是最优雅的解决方案,但应该可以工作。
SELECT column
FROM table
WHERE a = a1
AND (b = b1 OR (b != b1 AND (b = b2 OR (b != b2 AND b = b3))))

实际上,如果 b = b1 是假的,那么 b != b1 就是真的,没有必要再检查它。b = b2 也是类似的情况。因此,如果您删除不必要的条件,最终得到的查询与 OP 所请求的完全相同 :) 结果将是相同的,但这种解决方案效率较低 :P - Mosty Mostacho
短代码:a = a1 AND (b = b1 OR (b != b1 AND (b = b2 OR (b != b2 AND b = b3)))) - zanlok
现在我只有两个条件,即 (b = b1 OR (b != b1 AND (b = b2)))。如果这两个条件都为真,则会返回多行结果... - Nikita Silverstruk
我使用了NOT IN代替!=。在我的情况下,如果第一个条件为真,则使用!=检查第二个条件,返回true并且AND后面的条件也为true。因此它返回了2行并抛出了一个错误。 - Nikita Silverstruk
@Nikita 在 (b = b1 OR (b != b1 AND (b = b2))) 中,什么情况下两者都可以为真?你能澄清一下吗? - Chetter Hummin
@Amit Bhargava 在一个表中,我有一个起始城市和目的地以及一个承运商(这是一行)。另一个表中有一个承运商和分配给该承运商的城市。在这种情况下,我检查目的地城市是否在该承运商的城市列表中。如果不在,则检查起始城市是否在该表中。然而,如果起始城市和目的地都在第二个表中,那么两个条件都成立。无论如何,我使用了NOT IN,它起作用了。谢谢你的帮助! - Nikita Silverstruk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接