【问题标题】:Please correct this implementation of unique row selection (drop duplicates)请更正此唯一行选择的实现(删除重复项)
【发布时间】:2019-06-20 00:32:24
【问题描述】:

我正在尝试从 JOINed 表中选择唯一行

(忽略任何重复项,除了符合条件的重复项)

其中重复由在列post_title 中具有相同值的记录定义

将选择每个重复集中_meta_value 列中具有最低值的行。如果是 2 行之间的平局,则只需选择最低的行 post_IDID(唯一)。

到目前为止,这就是我所拥有的 - 它不起作用(返回零行) - 虽然意图应该很清楚,但我确定我没有使用正确的功能。

SELECT * FROM (

select wp_posts.ID, wp_posts.post_title, wp_postmeta.post_id, wp_posts.post_type, wp_postmeta.meta_key, wp_postmeta.meta_value
      from wp_postmeta JOIN wp_posts 
ON wp_postmeta.post_ID=wp_posts.ID

WHERE post_type = 'product' AND meta_key = '_regular_price'
    GROUP BY post_title
 ) as alias1
HAVING MIN(meta_value)

ORDER BY post_title

这是两个表的JOIN 之后请求的最小数据样本:

+-------------+---------------------+---------------------+--------------------+----------------------+------------------------+
| wp_posts.ID | wp_posts.post_title | wp_postmeta.post_id | wp_posts.post_type | wp_postmeta.meta_key | wp_postmeta.meta_value |
+-------------+---------------------+---------------------+--------------------+----------------------+------------------------+
|           1 | Apple Pie           |                   1 | Product            | _regular_price       |                     10 |
|           2 | French Toast        |                   2 | Product            | _regular_price       |                      5 |
|           3 | Shepards Pie        |                   3 | Product            | _regular_price       |                      9 |
|           4 | Jam Pie             |                   4 | Product            | _regular_price       |                      8 |
|           5 | Jam Pie             |                   5 | Product            | _regular_price       |                     11 |
|           9 | French Toast        |                   9 | Product            | _regular_price       |                     12 |
|          10 | French Toast        |                  10 | Product            | _regular_price       |                     12 |
+-------------+---------------------+---------------------+--------------------+----------------------+------------------------+

查询应该返回:

+-------------+---------------------+---------------------+--------------------+----------------------+------------------------+
| wp_posts.ID | wp_posts.post_title | wp_postmeta.post_id | wp_posts.post_type | wp_postmeta.meta_key | wp_postmeta.meta_value |
+-------------+---------------------+---------------------+--------------------+----------------------+------------------------+
|           1 | Apple Pie           |                   1 | Product            | _regular_price       |                     10 |
|           2 | French Toast        |                   2 | Product            | _regular_price       |                      5 |
|           3 | Shepards Pie        |                   3 | Product            | _regular_price       |                      9 |
|           4 | Jam Pie             |                   4 | Product            | _regular_price       |                      8 |
+-------------+---------------------+---------------------+--------------------+----------------------+------------------------+

【问题讨论】:

  • MySql 5.x 还是 8.x?我问这个是因为使用像 ROW_NUMBER 这样的窗口函数更容易做到这一点。
  • @Lukstorms 在我的测试服务器上 MyPHPAdmin 说 Server version: 10.1.37-MariaDB - mariadb.org binary distribution,在我的生产服务器上 MyPHPAdmin 说 Server version: 5.7.25 - MySQL Community Server (GPL)。这能回答你的问题吗?
  • 确实如此。这意味着您需要一个适用于 5.7 的 SQL。它没有 CTE 和窗口函数。 (但 MariaDB 10 可以)
  • @Strawberry 我在上面提供了一个数据集来解决您的问题。

标签: mysql mysql-5.7


【解决方案1】:

您可以使用 group by 并且 count(*) > 1 根据 post_title 的过滤器 (where) 获取副本

select wp_posts.post_title
from wp_postmeta 
JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID
    WHERE post_type = 'product' 
    AND meta_key = '_regular_price'
Group by wp_posts.post_title 
having count(*) > 1

您可以使用

获取这些重复项的最小 ID
select wp_posts.post_title, min(wp_posts.ID)
from wp_postmeta 
JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID
    WHERE post_type = 'product' 
    AND meta_key = '_regular_price'
Group by wp_posts.post_title 
having count(*) > 1

您不应该在查询中添加列广告..这是某些版本的 mysql 引发错误,而在其他版本中会产生不可预测的结果
相反,您应该使用带有 min(id) 的聚合结果作为子查询来连接您需要的值

select wp_posts.ID
    , wp_posts.post_title
    , wp_postmeta.post_id
    , wp_posts.post_type
    , wp_postmeta.meta_key
    , wp_postmeta.meta_value
from wp_postmeta 
JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID 
inner join  (
 select wp_posts.post_title, min(wp_posts.ID) min_id 
    from wp_postmeta 
    JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID
        WHERE post_type = 'product' 
        AND meta_key = '_regular_price'
    Group by wp_posts.post_title 
    having count(*) > 1

) t ON t.min_id  = wp_posts.ID  
        and  t.post_title = wp_posts.post_title 

但是,如果您希望 post_title 的所有第一个值与标题是否重复的事实无关(如在您的示例中),那么请避免使用子句 HAVING count(*) >1

select wp_posts.ID
, wp_posts.post_title
, wp_postmeta.post_id
, wp_posts.post_type
, wp_postmeta.meta_key
, wp_postmeta.meta_value
from wp_postmeta 
JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID 
inner join  (
  select wp_posts.post_title, min(wp_posts.ID) min_id 
  from wp_postmeta 
  JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID
    WHERE post_type = 'product' 
    AND meta_key = '_regular_price'
  Group by wp_posts.post_title 


 ) t ON t.min_id  = wp_posts.ID  
    and  t.post_title = wp_posts.post_title 

似乎问题是将尊重 min(wp_posts.ID) 更改为 p_postmeta.meta_value

select wp_posts.ID
, wp_posts.post_title
, wp_postmeta.post_id
, wp_posts.post_type
, wp_postmeta.meta_key
, wp_postmeta.meta_value
from wp_postmeta 
JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID 
inner join  (
  select wp_posts.post_title, min(wp_postmeta.meta_value) min_val
  from wp_postmeta 
  JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID
    WHERE post_type = 'product' 
    AND meta_key = '_regular_price'
  Group by wp_posts.post_title 


 ) t ON t.min_val  = wp_postmeta.meta_value
    and  t.post_title = wp_posts.post_title 

并排除相同元值的第二行 使用 min(id)

select wp_posts.ID
, wp_posts.post_title
, min( wp_postmeta.post_id)
, wp_posts.post_type
, wp_postmeta.meta_key
, wp_postmeta.meta_value
from wp_postmeta 
JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID 
inner join  (
  select wp_posts.post_title, min(wp_postmeta.meta_value) min_val
  from wp_postmeta 
  JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID
    WHERE post_type = 'product' 
    AND meta_key = '_regular_price'
  Group by wp_posts.post_title 


 ) t ON t.min_val  = wp_postmeta.meta_value
    and  t.post_title = wp_posts.post_title 
 group by  wp_posts.ID
, wp_posts.post_title
, wp_posts.post_type
, wp_postmeta.meta_key
, wp_postmeta.meta_value

【讨论】:

  • 出了点问题。当我在第二个代码块的第 1 行中使用 min(wp_metadata.meta_key) 时,返回的某些行带有空值 meta_key。这是你所期望的吗? (原始的wp_metadata.meta_key 不包含空值。)
  • 根据您的示例,我的查询不应该返回 meta_key 的空值 ... meta_key 应该只有 = '_regular_price' .. 您正在使用什么查询 .. ???
  • select wp_posts.ID, wp_posts.post_title, wp_postmeta.post_id, wp_posts.post_type, wp_postmeta.meta_key, wp_postmeta.meta_value, COUNT(wp_posts.post_title) AS c from wp_postmeta JOIN wp_posts ON wp_postmeta.post_ID=wp_posts.ID WHERE post_type = 'product' AND meta_key = '_regular_price' Group by wp_posts.post_title having count(c) > 1 我迷路了——我真的不知道我现在在做什么......
  • 如果您只想要重复的行,正确的结果应该是第 2 行和第 4 行 .. 否则,如果您想要所有 post_title 的第一行,则在这种情况下您将获得 1,2,3 ,4你不需要有 ...answer updated .. 希望是明确的条款
  • Answer udpated .. for meta_value ..但是对于相同的 min_value ,无论如何你有两个结果,这在你正在寻找 min_id 的第一个问题中似乎很奇怪 .. 所以 .. 我很失望。 . 似乎你已经改变了问题.. 否则为什么我的两个答案和下面的答案被引用为 min_id ??
【解决方案2】:

您可以通过简单的GROUP BY 和使用MIN 获得这些结果。

SELECT 
 MIN(p.ID) AS ID, 
 p.post_title, 
 MIN(pm.post_id) AS post_id, 
 p.post_type, 
 pm.meta_key, 
 MIN(pm.meta_value) AS meta_value
FROM wp_posts p 
JOIN wp_postmeta pm ON (pm.post_ID = p.ID AND pm.meta_key = '_regular_price')
WHERE p.post_type = 'product'
GROUP BY p.post_title, p.post_type, pm.meta_key
ORDER BY ID;

dbfiddle here

的测试

【讨论】:

  • 这不会从每个重复集中挑选出meta_value 最低的行吗?
  • 正确。因为我认为不需要获得预期的输出。您会看到,由于 INNER JOIN,wp_posts.ID 将始终与 wp_postmeta.post_ID 相同。由于标准,post_title 和 meta_key 是固定的。所以它只需要得到最小的meta_value。如果您需要 wp_postmeta.ID 作为最小值,那么是的,查询会有所不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-04
  • 1970-01-01
相关资源
最近更新 更多