SQL查询仍然在分组后有重复项

时间:2016-12-02 00:00:18

标签: mysql sql

SELECT *
FROM `eBayorders`
WHERE (`OrderIDAmazon` IS NULL
       OR `OrderIDAmazon` = "null")
  AND `Flag` = "True"
  AND `TYPE` = "GROUP"
  AND (`Carrier` IS NULL
       OR `Carrier` = "null")
  AND LEFT(`SKU`, 1) = "B"
  AND datediff(now(), `TIME`) < 4
  AND (`TrackingInfo` IS NULL
       OR `TrackingInfo` = "null")
  AND `STATUS` = "PROCESSING"
GROUP BY `Name`,
         `SKU`
ORDER BY `TIME` ASC LIMIT 7

我正在努力确保所有名称和skus都不会出现在同一个结果中。我试图按名称分组,然后sku,但是我遇到了一个问题,结果显示有相同的名称和不同的skus,我不想发生。如何修复此查询以确保结果集中始终存在不同的名称和skus?!

例如说我有订单:

Name: Ben Z, SKU : B000334, oldest
Name: Ben Z, SKU : B000333, second oldest
Name: Will, SKU: B000334, third oldest
Name: John, SKU: B000036, fourth oldest

The query should return only:
Name: Ben Z, SKU : B000334, oldest
Name: John, SKU: B000036, fourth oldest

这是因为所有名称在SKU中只有一个条目。

4 个答案:

答案 0 :(得分:2)

这里有两个问题。

第一个是ANSI标准,如果你有一个CSS.Property.BORDER_BOTTOM_COLOR子句,你可以放在GROUP BY子句中的唯一内容是SELECT中列出的项目或使用聚合函数(SUM,COUNT,MAX等)。您问题中的查询会选择表格中的所有列,即使是GROUP BY中没有的列。如果您有多个与组匹配的记录,则该表不知道要为这些额外列使用哪条记录。

MySql对此很愚蠢。理智的数据库服务器会抛出错误并拒绝运行该查询。 Sql Server,Oracle和Postgresql都会这样做。 MySql会猜测你想要的数据。让数据库服务器猜测数据通常不是一个好主意。

但这并没有解释重复的问题......为什么坏查询会运行。您有重复的原因是您在GROUP BYName上进行了分组。因此,例如,对于SKU的记录,您只想查看最旧的SKU。但是,当您对Ben ZName进行分组时,您会得到SKU{ Ben Z, B000334 }的单独组...这是Ben Z的两行,但它是查询的内容要求,因为SKU也是决定一个团体的一部分。

如果您只想查看每人一条记录,则只需按人员字段进行分组。这可能意味着首先构建查询的那一部分,以确定所需的基本记录集,然后作为完整解决方案的一部分加入此原始查询。

答案 1 :(得分:2)

SELECT T1.*
FROM eBayorders T1
JOIN
  ( SELECT `Name`,
           `SKU`,
           max(`TIME`) AS MAX_TIME
   FROM eBayorders
   WHERE (`OrderIDAmazon` IS NULL OR `OrderIDAmazon` = "null") AND `Flag` = "True" AND `TYPE` = "GROUP" AND (`Carrier` IS NULL OR `Carrier` = "null") AND LEFT(`SKU`, 1) = "B" AND datediff(now(), `TIME`) < 4 AND (`TrackingInfo` IS NULL OR `TrackingInfo` = "null") AND `STATUS` = "PROCESSING"
   GROUP BY `Name`,
            `SKU`) AS dedupe ON T1.`Name` = dedupe.`Name`
AND T1.`SKU` = dedupe.`SKU`
AND T1.`Time` = dedupe.`MAX_TIME`
ORDER BY `TIME` ASC LIMIT 7

您的数据库平台应该投诉,因为您的原始查询在选择列表中的项目不在组中(通常不允许)。以上应该解决它。

如果你的数据库支持窗口函数(不幸的是,MySQL没有),那么更好的选择是:

SELECT *
FROM
  ( SELECT *,
           row_number() over (partition BY `Name`, `SKU`
                              ORDER BY `TIME` ASC) AS dedupe_rank
   FROM eBayorders
   WHERE (`OrderIDAmazon` IS NULL OR `OrderIDAmazon` = "null") AND `Flag` = "True" AND `TYPE` = "GROUP" AND (`Carrier` IS NULL OR `Carrier` = "null") AND LEFT(`SKU`, 1) = "B" AND datediff(now(), `TIME`) < 4 AND (`TrackingInfo` IS NULL OR `TrackingInfo` = "null") AND `STATUS` = "PROCESSING" ) T
WHERE dedupe_rank = 1
ORDER BY T.`TIME` ASC LIMIT 7

答案 2 :(得分:1)

您正在尝试获取SKU和Name列中没有重复的结果集。

您可能需要在查询中添加subquery才能完成此操作。内部查询将按名称分组,外部查询将按SKU分组,这样您就不会在任一列中重复。

试试这个:

SELECT *
FROM
  (SELECT *
   FROM eBayorders
   WHERE (`OrderIDAmazon` IS NULL
          OR `OrderIDAmazon` = "null")
     AND `Flag` = "True"
     AND `TYPE` = "GROUP"
     AND (`Carrier` IS NULL
          OR `Carrier` = "null")
     AND LEFT(`SKU`, 1) = "B"
     AND datediff(now(), `TIME`) < 4
     AND (`TrackingInfo` IS NULL
          OR `TrackingInfo` = "null")
     AND `STATUS` = "PROCESSING"
   GROUP BY Name)
GROUP BY `SKU`
ORDER BY `TIME` ASC LIMIT 7

答案 3 :(得分:0)

使用这种方法,您只需过滤掉不包含TIME的最大/最新值的行。

SELECT SKU, Name
FROM eBayOrders o
WHERE NOT EXISTS (SELECT 0 FROM eBayOrders WHERE Name = o.name and Time > o.Time)
GROUP BY SKU, Name

注意:如果两个记录具有完全相同的名称和时间值,您可能仍然会得到重复项,因为您指定的逻辑没有提供任何方法来打破平局。