【问题标题】:sql having get only the first recorded row in table and i want allsql 只获得表中记录的第一行,我想要所有
【发布时间】:2012-07-29 12:11:17
【问题描述】:

有人已经帮助我完成了这个查询,但我做了修改,但遇到了问题:

    SELECT 
        AVG(tyd.price) AS avg_price, COUNT(tyd.id_product) AS cnt, 
        tyd.id_marchand, tyd.id_product, 
        catalog.price AS c_price, tyd.price AS t_price, 
        tyd.amount AS t_am, pro_tyd.amount AS p_am, 
        pro_tyd.price AS p_price, catalog.img_src,  
        tyd.step, tyd.login AS tyd_l
    FROM catalog 
    INNER JOIN tyd ON catalog.id_marchand = tyd.id_marchand 
                   AND catalog.id_product =   tyd.id_product
                   AND tyd.step = "1" 
    INNER JOIN pro_tyd  ON tyd.id_marchand = pro_tyd.id_marchand 
                        AND tyd.id_product = pro_tyd.id_product
    GROUP BY 
         catalog.id_product, catalog.id_marchand
    HAVING 
         tyd.login = "user1@tyd.fr"

并且它仅在tyd.login = "user3@tyd.fr" 是较低的 id 时有效。不适用于 user1 或 user2...我只是不知道为什么...!如果我按 tyd.login 分组,它也可以工作,但在这种情况下,AVG 和 COUNT 函数只能在一行上工作......

这是表格:

id  id_marchand  id_product   login       price  amount  delay  step    time   
29      1           1       user3@tyd.fr   344     1       0      1   1343297500
120     1           1       user1@tyd.fr   54      1       0      1   1343297504
109     1           1       user10@tyd.fr  34      1       0      1   1343298598

HAVING tyd.login = "user3@tyd.fr" 完美运行。当 user1 或 user2 我得到 0 行。

感谢您的帮助

第一个主题:Sql, get the average on a group while escaping the where condition

【问题讨论】:

  • 你在滥用HAVING,它通常用于组过滤或聚合函数。我认为您应该只使用WHERE tyd.login = "user1@tyd.fr"。此外,您没有“user1”,而是“user10”。
  • 如果我不使用 having 子句,我只会得到 userX 行的 AVG 和 COUNT。我想要每行的 AVG 和 COUNT 相同的 id_product 和 id_marchand。对不起 user1 和 10,我更正了。
  • 您到底想从这个查询中得到什么? 当 HAVING tyd.login = "user3@tyd.fr" 它完美运行时是什么意思。。你能解释一下吗?
  • 我想要 id_product 和 id_marchand 等于 id_product 和 id_marchand WHERE step = 1 HAVING userX in login 的每一行的 AVG 和 COUNT。然后是这条线的其他选择的东西。我提出的要求是独一无二的。对于同一产品,用户不能两次进入 step = 1。
  • 当我使用 HAVING tyd.login = "user3" 进行查询时,我得到了整个 AVG & COUNT + 我为该行选择的行。当我输入 HAVING tyd.login = user10 时,我得到一个空答案。 user3 和 user1 行之间的唯一区别是记录顺序。例如,如果我删除 user3 行,查询将适用于 user1,但不适用于 user10。

标签: sql join group-by having average


【解决方案1】:

问题是您的查询是不确定的。您正在选择更多要分组的列,其中附加列不是由您分组的列确定的。如果后者是真的,那么这将属于 SQL 的 ANSII 标准,因为它根本不是(在我看来)MySQL 的失败,它允许语句运行。其他 DBMS 则采取了相反的方式,因为它们无法确定某些列是否是未包含在 group by 中的其他列的函数,它们现在将允许任何包含未包含在 group by 中的选择列表中的列的语句。

要尝试简化问题,请使用以下数据集(表 T)

ID    Col1    Col2
1     1       1
2     1       3

运行这个:

SELECT Col1, MAX(Col2) AS MaxCol2, MIN(Col2) AS MinCol2, AVG(Col2) AS AvgCol2
FROM T
GROUP BY Col1

总会回来

Col1    MaxCol2    MinCol2    AvgCol2
1       3          1          2

但是,如果您将ID 加入其中

SELECT ID, Col1, MAX(Col2) AS MaxCol2, MIN(Col2) AS MinCol2, AVG(Col2) AS AvgCol2
FROM T
GROUP BY Col1

无法确定返回哪个ID,1还是2,最有可能的结果是

ID    Col1    MaxCol2    MinCol2    AvgCol2
1    1       3          1          2

但是,SQL 中没有定义任何内容来说明结果不可能:

ID    Col1    MaxCol2    MinCol2    AvgCol2
2     1       3          1          2

因此,如果以上是结果集,并且您将 HAVING ID = 1 添加到查询中,由于 HAVING 子句应用于数据的点,您将不会得到任何结果。如果您要将 ID 添加到 GROUP BY 您最终会得到 2 行,据我了解这不是您想要的,如果您要将其添加到 WHERE 您的 MIN、MAX 和 AVG 函数将被影响。所以你需要使用子查询。所以在这个例子中我会使用

SELECT  T.ID, T.Col1, MaxCol2, MinCol2, AvgCol2
FROM    T
        INNER JOIN
        (   SELECT Col1, MAX(Col2) AS MaxCol2, MIN(Col2) AS MinCol2, AVG(Col2) AS AvgCol2
            FROM T
            GROUP BY Col1
        ) T2
            ON T.Col1 = T2.Col1
WHERE   ID = 1 -- OR ID = 2 DEPENDING ON REQUIREMENTS

为了将此应用于您的情况,数据库引擎已确定将为不在 group by 中的列返回的行是包含 ID = 29 的行。因此您的 HAVING 子句仅适用于该行,在应用 HAVING 子句时,已经从结果中删除了 user1@tyd.fr 和 user10@tyd.fr 的行。您需要单独执行聚合函数来过滤。

现在我还没有完全理解您的架构,但我希望我已经充分解释了非确定性语句的问题,以便您可以对我尝试重写您的查询进行任何修改

SELECT  Avg_Price,
        Cnt,
        tyd.id_marchand, 
        tyd.id_product, 
        catalog.price AS c_price, 
        tyd.price AS t_price, 
        tyd.amount AS t_am, 
        pro_tyd.amount AS p_am, 
        pro_tyd.price AS p_price, 
        catalog.img_src,  
        tyd.step, 
        tyd.login AS tyd_l
FROM    Catalog
        INNER JOIN tyd
            ON catalog.id_marchand = tyd.id_marchand 
            AND catalog.id_product = tyd.id_product
        INNER JOIN Pro_tyd
            ON tyd.id_marchand = pro_tyd.id_marchand 
            AND tyd.id_product = pro_tyd.id_product
        INNER JOIN
        (   SELECT  ID_Marchand, ID_Product, Step, AVG(tyd.price) AS avg_price, COUNT(tyd.id_product) AS cnt
            FROM    Tyd
            WHERE   Step = '1'
            GROUP BY ID_Marchand, ID_Product, Step
        ) Agg
            ON Agg.id_marchand = pro_tyd.id_marchand 
            AND Agg.id_product = pro_tyd.id_product
            AND Agg.Step = tyd.Step
WHERE   tyd.Login = 'user1@tyd.fr'

【讨论】:

  • 我完全同意并理解您的解释。我没有尝试您的解决方案,但我会并且我不熟悉子查询,所以它对我有帮助。但是,如果我关注您的帖子,问题应该与那里的查询相同(Marco):stackoverflow.com/questions/11740458/… 但我得到了所有的线路,而不仅仅是第一条线路。在该查询中,具有不是对一行的选择性。但可能不是完全相同的逐行分组。我会尽快看的。非常感谢您的帮助。
  • 所以你给我的查询是完美的工作。但实际上,我不明白为什么它使用 step =“0”而不是 step =“1”。你认为我必须按照你告诉我的那样重写第一个查询吗?
  • 我已经用可能的解决方案更新了答案。我仍然不确定您到底在追求什么,或者平均值应该是什么或应该如何分组。但希望新的查询能让您朝着正确的方向前进。
  • 对不起,我表达错误。您给我的查询完全符合我的预期!我不明白的是为什么 Marco 在那里给我的查询:stackoverflow.com/questions/11740458/… 适用于 step = 0 而不适用于 step = 1。当 step = 0 时我得到好的结果,当 step = 1 我得到空结果...我想了解为什么会这样。但是非常感谢您的完美查询!
【解决方案2】:

我只想添加这个查询:

SELECT * FROM  tyd WHERE step = "1" 
GROUP BY tyd.id_product, tyd.id_marchand 
HAVING tyd.login = "user1@tyd.fr" 

有同样的问题。在 tyd.login = "user3" 时有效,但在询问其他用户时无效...

【讨论】:

  • 如果你在第一篇文章中使用我的桌子,我会得到这一行:120 / 1 / 1 / user3@tyd.fr / 432 (354 + 44 + 34 /3) / 3 (1+1 +1) / 1 / time...当我输入 HAVING login = user3 和零行时 HAVING login = user1
猜你喜欢
  • 2015-11-04
  • 2016-12-18
  • 1970-01-01
  • 2018-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
相关资源
最近更新 更多