即使第二个表没有相应的条目,也可以从2个db表中获取查询结果

时间:2012-08-31 18:53:33

标签: php mysql sql

这是我的问题:即使第二个表没有相应的条目,也可以从2个db表中获取查询结果。

以下是我在SQL中使用的一些示例代码

SELECT DISTINCT apps.id, apps.*, req.status
FROM applications AS apps, requests AS req
WHERE apps.id = {$app_id}

但问题是它不会提取没有request.status值/条目的应用程序,所以问题是:是否可以修改这个简单的查询来为所有应用程序提取结果。*行即使没有相应的requests.status row / entry?

编辑BELLOW:

所以这是我从我得到的反馈中得到的新查询(这很好)

SELECT DISTINCT 
    apps.*, req.status
FROM 
    applications AS apps
    LEFT JOIN requests AS req ON (req.app_id = apps.id AND req.uid = {$user_id})
WHERE 
    apps.id = {$app_id}

BUT:当我在where子句中添加一个新表达式来过滤请求状态时,我得到与隐式查询相同的问题,我没有得到结果(查询如下)

SELECT DISTINCT 
    apps.*, req.status
FROM 
    applications AS apps
    LEFT JOIN requests AS req ON (req.app_id = apps.id AND req.uid = {$user_id})
WHERE 
    apps.id = {$app_id}
AND
    (req.status = 2 OR req.status = 5)

另一个编辑

这是要查看的更新代码。 现在的问题是,如果我添加子查询,子查询将拉出所有行,然后将NULL作为状态列的值,但是只要我添加WHERE状态!= 2它就会删除所有条目,不应该这仍然有所有行为null?因为null显然是!= 2。

SELECT DISTINCT
    apps . *
FROM
    (SELECT 
        apps . *, req.status
    FROM
        appstore_app AS apps
    LEFT JOIN app_user_request AS req ON (req.uid = 187 AND req.appid = apps.appid)
    WHERE
        apps.appid > 0 AND apps.company_id = 122) AS apps
WHERE
    apps.status != 2
ORDER BY apps.average_user_rating DESC

最终编辑

感谢所有帮助!

这是我的最终查询对我有用:

SELECT 
    apps.*, req.status
FROM
    appstore_app AS apps
        LEFT JOIN
    app_user_request AS req ON (req.uid = {$user_id} AND req.appid = apps.appid AND (req.status IS NULL OR req.status != 2))
WHERE
    apps.appid > 0 AND apps.company_id = {$company_id}

6 个答案:

答案 0 :(得分:0)

您的查询使用隐式交叉连接,从两个表中选择数据,而不指定关联两个表的方法。你真正想要的是一个左连接。

SELECT DISTINCT apps.id, apps.*, req.status
    FROM applications AS apps
        LEFT JOIN requests AS req
            ON apps.id = req.apps_id /* Guessing on the relationship here */
    WHERE apps.id = {$app_id}

一旦语法正确,请查看此查询是否真的需要DISTINCT。这可能是昂贵的开销,可以消除。

编辑:添加以下部分以回复编辑过的问题。

在WHERE子句中测试LEFT JOINed列(在您的情况下为req.status)时,强制该连接的行为就像它是INNER JOIN一样。相反,将这些测试作为连接条件的一部分。

SELECT DISTINCT 
    apps.*, req.status
FROM 
    applications AS apps
    LEFT JOIN requests AS req ON (req.app_id = apps.id AND req.uid = {$user_id})
        AND  (req.status = 2 OR req.status = 5)
WHERE 
    apps.id = {$app_id}

答案 1 :(得分:0)

SELECT DISTINCT 
  apps.*, req.status
FROM 
  applications AS apps
  LEFT JOIN requests AS req on req.app_id = apps.id
WHERE 
  apps.id = {$app_id}

答案 2 :(得分:0)

即使没有相应的requests.status,LEFT JOIN也会显示所有应用程序。

SELECT DISTINCT apps.id, apps.*, req.status
FROM applications apps
LEFT JOIN requests req ON req.? = applications.?
WHERE apps.id = {$app_id}

您需要添加将两个表链接在一起的列(?)。

答案 3 :(得分:0)

你需要使用这样的显式LEFT JOIN:

SELECT DISTINCT apps.id, apps.*, req.status
FROM applications AS apps
LEFT JOIN requests AS req ON apps.whatever_field_relates = req.whatever_field_relates
WHERE apps.id = {$app_id}

FROM table1, table2一样使用隐式JOINS并不是IMO的好习惯。这使得其他程序员很难在不必参考数据库模式的情况下一目了然地了解JOIN的确切性质。

答案 4 :(得分:0)

SELECT DISTINCT app.*,req.status 
from applications apps 
left join request as req on req.appid = apps.id
where apps.id ={$app_id}

做一个左连接就可以了,我习惯了TSQL语法,但我相信它可以在Mysql中运行。您需要在两个表格中使用您的应用的ID,才能加入它们。

答案 5 :(得分:0)

O.P。表示:

  

BUT:当我向where子句添加新表达式以过滤请求状态时,i>得到与隐式查询相同的问题,我没有得到结果(查询如下)

SELECT DISTINCT 
       apps.*,
       req.status
FROM applications  apps
LEFT JOIN requests req ON req.app_id = apps.id
                      AND req.uid    = {$user_id}
WHERE apps.id = {$app_id}
  AND (    req.status = 2
        OR req.status = 5
      )

问题是where子句过滤了结果集,因此对req.status的2或5的测试会抛出req.status为空的任何内容,因为没有与表匹配的行applications

一般的,理论上的(因为除了一个简单的实现之外什么都不会做这样的事情)select语句的操作顺序是:

  • 生成from子句中列出的每个表的完整笛卡尔积。
  • 通过应用指定的join条件对其进行过滤,并删除未通过指定测试的行。
  • 应用where子句中指定的过滤条件,删除未通过指定测试的行。
  • group by子句中指定的表达式上对结果集进行排序,并将结果集合分组。
  • 将每个此类组折叠为一行,计算所有指定聚合函数的值。
  • 从结果集中删除select语句列列表中未列出的所有列。
  • 按照order by子句中指定的列/表达式对此最终结果进行排序。

你可以做以下两件事之一:

  • 更改您的查询以测试无效:

    where...( req.status is null OR req.status in (2,5) )...
    
  • 将针对req.status的测试移至加入条件:

    left join requests req on req.app_id =  apps.id
                          and req.uid    =  {$user_id}
                          and req.status in (2,5)