仅当满足两个条件时才在单个 sql 语句中选择两行

Selecting two rows in a single sql statement only if both conditions are met

我有一个 table,其中包含以下数据。

table name: myTable

prodID   catNo   variable1  variable2
1        20      Cat        Blue
2        10      Cat        Red
2        15      Cat        Green
2        20      Cat        Black
3        20      Cat        Yellow
4        10      Cat        Orange
4        15      Cat        Brown
4        20      Cat        Black
5        30      Cat        Pink

我希望能够 select myTable 中满足以下条件的所有列
"(prodID = 2 and catNo = 10) AND (prodID = 2 and catNo = 15)”。因此,只有在满足两个条件的情况下才会得到两行的结果,如果两行都不存在,它将 return 什么都没有。 所以我的结果 table 将如下所示。

table name: results

prodID   catNo   variable1  variable2
2        10      Cat        Red
2        15      Cat        Green

我试过使用条件 if 语句,但似乎无法让它们在 sql 中工作。我目前的解决方案是取回 prodID = 2 的所有行,然后使用 php 执行 if 语句来决定显示什么,但这不适用于我为显示结果而设计的分页limit 会扭曲每页的结果数。 我知道我可以使用 'having count rows=2' 但我不确定如何表达它。

条件应该是 (prodID = 2 and catNo = 10) OR (prodID = 2 and catNo = 15)

如果您只想在 catNo (10,15) 中找到记录时获得结果,但如果您在 (10,12)

中查找 catNo 也想获得 return 0 个结果
SELECT * FROM `myTable` 
WHERE (`prodID` = 2 AND `catNo` IN (10,15)) 
AND (SELECT COUNT(`catNo`) FROM `myTable` WHERE `prodID` = 2 AND `catNo` IN (10,15))>1;

三个目录号

SELECT * FROM `myTable` 
WHERE (`prodID` = 4 AND `catNo` IN (10,15,20)) 
AND (SELECT COUNT(`catNo`) FROM `myTable` WHERE `prodID` = 4 AND `catNo` IN (10,15,20))>2;

SQL Fiddle

使用下面的 SQL 查询。

SELECT * FROM myTable where prodID = 2 and (catNo = 10 OR catNo = 15)

希望对您有所帮助

试试这个它会起作用:

SELECT * FROM `myTable` WHERE `prodID` = '2' AND `catNo` IN ('10','15')

要匹配同一产品的两个类别,您可以这样做

select t.*
from table1 t
join (
select prodID
from table1
where catNo in (10,15)
and prodID = 2
group by prodID
having count(distinct catNo ) = 2
  ) t2
using(prodID)
where t.catNo in (10,15)

DEMO

 SELECT DISTINCT a.*,b.catNo,c.catNo FROM myTable AS a
 JOIN mytable AS b ON b.prodID=a.prodID
 JOIN mytable AS c ON c.prodID=a.prodID
 WHERE a.prodID=2 AND b.catNo=10
 AND c.catNo=15;

这个有效。这个问题真的很棘手。

谢谢作品。我设法想出了一个不需要连接的解决方案,它有一个非常大的 table 像我的那样会很慢:

select * 
from myTable 
where ((prodID = 2 and catNo = 10) or (prodID = 2 and catNo = 15)) 
group by catNo
having (
        select count(distinct(catNo))
        from myTable 
        where ((prodID = 2 and catNo = 10) or (prodID = 2 and catNo = 15))
)=2;  

发布的大多数解决方案都缺少关于 return 什么都没有的部分,除非两个条件都满足。因此,如果满足一个且仅一个条件,大多数解决方案都会失败,因为它们仍然 return 一行而不是 none.

假设您希望能够检查任意数量的 WHERE 条件,而不仅仅是两个,您可以使用基于子查询的解决方案。

使用这种方法,您可以在输出之前检查结果集中符合条件的行数。有几种方法可以做到这一点,但我们的想法是将符合条件的行数与您预期的行数进行比较。如果它们匹配,则输出行。如果它们不匹配,return 一个空结果集。

M Khalid Junaid 发布了一个解决方案,该解决方案使用 group by 和子查询中的 having 条件来检查结果集大小是否为 2。此解决方案适用于您的特定示例和其他类似示例。如果您的 WHERE 条件变得更加复杂或变化,则可能不会,因为它依赖于 ProdID 在每个 WHERE 条件下都相同,但原则是合理的。此外,此特定方法要求针对源 table 处理 WHERE 条件两次,而下面的方法只处理一次。对于非常大的 tables and/or 许多 WHERE 条件,这种方法应该更有效。

您可以像其他示例一样直接在 FROM 条件中构造子查询,也可以通过 WITH 语句构造子查询。我在这里使用了后者,因为它更清楚地显示了正在发生的事情:

With ResultSet as (select * from myTable
        where (prodID = 2 AND catNo = 10) OR (prodID = 2 AND catNo = 15)), -- your WHERE condition
    TotalRows as (select COUNT(*) as TRows from ResultSet) -- count of result set
select ResultSet.*
from ResultSet
    inner join TotalRows on 1=1 -- force the join to work no matter what the tables contain
where TRows = 2 -- this is where you check against how many result rows you expect

"ResultSet" 子查询是您的 WHERE 原因所在,它可以根据需要简单或复杂。 "TotalRows" 计算结果集,因此只包含一行。然后将子查询连接在一起,但如果结果集计数 (TRows) 与后面的预期行大小匹配,则只输出前者的行。

你可以尝试写一个函数。很长但很容易理解

DROP FUNCTION getIt();
CREATE OR REPLACE FUNCTION getIt()
RETURNS TABLE (prodID INTEGER, catNo INTEGER, variable1 TEXT, variable2 TEXT) AS
$BODY$
BEGIN
  IF (CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"=2 and "catNo" = 10) AS INTEGER)>0 AND CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"=2 and "catNo" = 15) AS INTEGER)>0)
  THEN RETURN QUERY SELECT * 
     FROM "myTable" 
     where "prodID"=2 and ("catNo" = 10 or "catNo" = 15 );
  END IF;
END;
$BODY$ 
LANGUAGE 'plpgsql';
SELECT * FROM getIt();

可以参数化

DROP FUNCTION getIt(pid integer, cid1 integer, cid2 integer);
CREATE OR REPLACE FUNCTION getIt(pid integer, cid1 integer, cid2 integer)
RETURNS TABLE (prodID INTEGER, catNo INTEGER, variable1 TEXT, variable2 TEXT) AS
$BODY$
BEGIN
  IF (CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"= and "catNo" = ) AS INTEGER)>0 AND CAST ((SELECT "prodID" 
     FROM "myTable" 
     where "prodID"= and "catNo" = ) AS INTEGER)>0)
  THEN RETURN QUERY SELECT * 
     FROM "myTable" 
     where "prodID"= and ("catNo" =  or "catNo" =  );
  END IF;
END;
$BODY$ 
LANGUAGE 'plpgsql';
SELECT * FROM getIt(2, 10, 15);