搜索查询中多个具有count(*)的表吗?

时间:2019-02-24 20:09:07

标签: php mysql search

我有一个在线商店的搜索字段,该站点使用MySQL查询两个不同的表。第一个表是具有13列的 vinyls ,第二个表是具有10列的 products 。我想要的结果是,如果您输入一个关键字,它将搜索表 vinyls 中的专辑名称 artist_name 列,以及产品中的名称列以查找任何匹配项。

我的php代码首先计算匹配的次数,如果匹配,则再次使用查询来显示匹配,就像在线商店一样。但是,当我对其进行测试时,它仅显示 vinyls 表中的结果,而不显示 products 表中的结果。我尝试使用 UNION ,但是由于两个表的列数不同,因此会导致错误。我已经使用 NULL 来填充 union 所需的缺少的列,但是它也不起作用。联接也无济于事,因为两个表没有任何相似的列。麻烦的是在第一个查询中使用count(*)。

我的SQL查询使用UNION和COUNT:

(SELECT COUNT(*) AS numrows 
FROM vinyls 
WHERE (     album_name LIKE :keyword 
        OR  artist_name LIKE :keyword)
      ) 
union 
(SELECT COUNT(*) AS numrows 
FROM products 
WHERE name LIKE :keyword)

我用于搜索字段的php代码:

$stmt = $conn->prepare("(SELECT COUNT(*) AS numrows 
                        FROM vinyls 
                        WHERE (     album_name LIKE :keyword 
                                OR  artist_name LIKE :keyword)
                              ) 
                        union 
                        (SELECT COUNT(*) AS numrows 
                        FROM products 
                        WHERE name LIKE :keyword)");

$stmt->execute(['keyword' => '%'.$_POST['keyword'].'%']);
$row = $stmt->fetch();


if($row['numrows'] < 1){
    echo '<h1 class="page-header">No results found for <i>'.$_POST['keyword'].'</i></h1>';
}else{
    echo '<h1 class="page-header">Search results for <i>'.$_POST['keyword'].'</i></h1>';
    try{
        $inc = 3;   
        $stmt = $conn->prepare("(SELECT * 
                                FROM vinyls 
                                WHERE (     album_name LIKE :keyword 
                                        OR  artist_name LIKE :keyword)
                                    ) 
                                union 
                                (SELECT * 
                                FROM products 
                                WHERE name LIKE :keyword)");

        $stmt->execute(['keyword' => '%'.$_POST['keyword'].'%']);

        foreach ($stmt as $row) {...

我已经很困惑如何仅从一个搜索字段中搜索2个表并显示两个表(而不只是一个表)的结果。而且,在将商品添加到购物车中时,这也是一个类似的问题,因为它们可以来自两个表,而我必须再次“联接”这两个表。

我哪里出错了?

编辑: 样本数据 Vinyls table +----+------------------+---------------------------+-----------+ | id | album_name | artist_name | genre | +----+------------------+---------------------------+-----------+ | 11 | Ravel Bolero | Boston Symphony Orchestra | Classical | | 12 | TV Calendar Show | Arthur Godfrey | Orchestra | | 13 | Flip Phillips | The Phillips Quartet | Jazz | | 14 | The Modern Idiom | Various artists | Jazz | +----+------------------+---------------------------+-----------+

Products table +----+-------------+------------------------------------------------------+ | id | category_id | name | +----+-------------+------------------------------------------------------+ | 31 | 15 | Tonka/Diecast trucks and cars | | 32 | 21 | Plate Number Georgia PQQ 1151 | | 33 | 6 | Walt Disney Read Along Casette Tapes | | 34 | 7 | Herbert Von Karajan | | 35 | 8 | BANK IT! Board Game | | 36 | 9 | Iraqi Most Wanted Playing Cards | | 37 | 10 | STAR TREK ( 1991,'92,'93 ) Stamp Oasis Rubber Stamps | | 38 | 11 | Batman and Friends Action Figure Toys (4" - 5") | | 39 | 12 | Delta Dawn Porcelain Doll | +----+-------------+------------------------------------------------------+

预期结果类似于亚马逊的搜索栏,在其中键入关键字并在输入后显示结果。我要在网站上显示的是,如果我在搜索字段中输入管弦乐队,它将显示“波士顿交响乐团”的行。或者,如果我输入汽车,它将显示tonka行。

我得到的是,即使我键入了cars,并且product表中应该有一个匹配项,它也只显示 vinyls 表,而不显示 products 表。或者我收到一个错误,因为联合仅适用于具有相似列数的表。

1 个答案:

答案 0 :(得分:1)

您的代码中有2个问题。

首先,您的计数查询应该可以正常工作并且不会引发任何错误,但是您只查看第一结果行(您的乙烯基之一)。但是您的查询返回两行。 (它将为您的联合中的第一个联合查询(乙烯基)返回带有numrows字段的一行,为第二个查询(产品)返回具有numrows字段的一行。

您可以将其包装到SUM中,以仅返回一个结果行:

$stmt = $conn->prepare("SELECT SUM(numrows) AS numrows FROM
                        (SELECT COUNT(*) AS numrows 
                        FROM vinyls 
                        WHERE (     album_name LIKE :keyword 
                                OR  artist_name LIKE :keyword)
                              ) 
                        union 
                        (SELECT COUNT(*) AS numrows 
                        FROM products 
                        WHERE name LIKE :keyword)) AS sumQuery");

第二个问题是查询,由于列数不匹配,该查询将加载结果并引发异常。您必须定义应返回两个联合查询中的每一个的哪些列,并且它们必须在两者上都匹配。所以做到这一点:

        $stmt = $conn->prepare("(SELECT id, album_name AS name, artist_name
                                FROM vinyls 
                                WHERE (     album_name LIKE :keyword 
                                        OR  artist_name LIKE :keyword)
                                    ) 
                                union 
                                (SELECT id, name, NULL AS artist_name
                                FROM products 
                                WHERE name LIKE :keyword)");