当我觉得它应该是相同的时,获得不同的SQL结果

时间:2015-07-02 16:05:00

标签: mysql sql tsql

所以我有一个我正在尝试运行的查询。现在它正在我的代码中循环运行并对每个邻居ID进行选择。我宁愿它做一个选择,只是循环通过这些结果,因为这是对数据库imho的命中。无论如何,我无法弄清楚为什么这两个查询给我不同的结果:

第一次查询:

SELECT `neighbourhood_id`,
    SUM(IF(`c`.`listing_offer` = 1, 1, 0)) as `listing_for_sale`,
    AVG(IF(`c`.`listing_offer` = 1, `price`, 0)) as `avg_sale_price`,
    SUM(IF(`c`.`listing_offer` = 2, 1, 0)) as `listing_for_rent`,
    AVG(IF(`c`.`listing_offer` = 2, `price`, 0)) as `avg_rent_price`
FROM (
    SELECT `n`.`id` AS `neighbourhood_id`, `l`.*
    FROM `listing` `l`
        LEFT JOIN `address` `a` ON `l`.`address_id` = `a`.`id` 
        LEFT JOIN `address_neighbourhood` `an` ON `a`.`id` = `an`.`address_id` 
        LEFT JOIN `neighbourhood` `n` ON `an`.`neighbourhood_id` = `n`.`id` 
        WHERE (`l`.`deleted`=0) 
            AND `n`.`id` IS NOT NULL
            AND `n`.`id` = 1
        GROUP BY `l`.`id`
    ) `c`
GROUP BY `neighbourhood_id`

结果:

neighbourhood_id    listing_for_sale    avg_sale_price  listing_for_rent    avg_rent_price
1                   7541                486634.853967   4045                786.372706

第二次查询:

SELECT `neighbourhood_id`,
    SUM(IF(`c`.`listing_offer` = 1, 1, 0)) as `listing_for_sale`,
    AVG(IF(`c`.`listing_offer` = 1, `price`, 0)) as `avg_sale_price`,
    SUM(IF(`c`.`listing_offer` = 2, 1, 0)) as `listing_for_rent`,
    AVG(IF(`c`.`listing_offer` = 2, `price`, 0)) as `avg_rent_price`
FROM (
    SELECT `n`.`id` AS `neighbourhood_id`, `l`.*
    FROM `listing` `l`
        LEFT JOIN `address` `a` ON `l`.`address_id` = `a`.`id` 
        LEFT JOIN `address_neighbourhood` `an` ON `a`.`id` = `an`.`address_id` 
        LEFT JOIN `neighbourhood` `n` ON `an`.`neighbourhood_id` = `n`.`id` 
        WHERE (`l`.`deleted`=0) 
            AND `n`.`id` IS NOT NULL
        GROUP BY `l`.`id`
    ) `c`
WHERE `neighbourhood_id` = 1
GROUP BY `neighbourhood_id`

结果:

neighbourhood_id    listing_for_sale    avg_sale_price  listing_for_rent    avg_rent_price  
1                   5740                522544.830430   2870                762.646690

我很确定查询1是正确的结果,所以我不确定为什么我在第二个查询上得到不同的结果。我仍然需要纠正,但哪一个是正确的。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

使用第一个分组,然后条件过滤记录集。现在关键是没有必要通过维持秩序来组。您的两个查询的子查询都会以不同的顺序返回结果,之后会为过滤器创建问题。

条件是AND邻域. id = 1在第一个查询中的Form Subquery 'c'的where子句中,此条件位于主查询的Where子句中。这意味着在第二个查询的子查询c的记录集中,这些记录集可以具有除{1}之外的neighbourhoodid值以及在该组之后使用的记录集,其中任何记录的值可以是来自该记录集的任何事物。但是在第一个子查询中,只选择那些记录集neighbourhoodid = 1 e,并按结果分组,记录可以包含value neighbourhoodid = 1。

例如,

你的第二个查询的子查询c选择了一个n.id = 0的记录,但是这条记录将被拒​​绝而不在外部查询中使用,因为n.id=1正在测试,所以不使用内部查询结果。但是在第一个查询的子查询c中将选择那些n.id=1并且它将始终用于外部查询的记录。因此两种结果都不同。

假设子查询c是 -

SELECT `l`.`id` , `n`.id
    FROM `listing` `l`
        LEFT JOIN `address` `a` ON `l`.`address_id` = `a`.`id` 
        LEFT JOIN `address_neighbourhood` `an` ON `a`.`id` = `an`.`address_id` 
        LEFT JOIN `neighbourhood` `n` ON `an`.`neighbourhood_id` = `n`.`id` 
        WHERE (`l`.`deleted`=0) 
            AND `n`.`id` IS NOT NULL;

是结果 -

(l.id , n.id) (1,0),(1,1)

当使用group by时它返回 -

(l.id , n.id) (1,0) 

并且外部查询中不使用此记录。

但在第一次查询子查询时结果将是

(l.id , n.id) (1,1) 

,它用于外部查询。

答案 1 :(得分:0)

答案是你试图立刻做太多。您不希望通过列出ID来访问该组(我不认为您这样做,如果需要,您需要在最内层查询中使用聚合)。我相信这是你真正需要的(注意聚合都是SUM):

nLA ((1,1),(1,n)) xs