1

我有一个tbl_entries具有以下结构的表:

+----+------+------+------+
| id | col1 | col2 | col3 |
+----+------+------+------+
| 11 |    a |    b |    c |
| 12 |    d |    e |    a |
| 13 |    a |    b |    c |
| 14 |    X |    e |    2 |
| 15 |    a |    b |    c |
+----+------+------+------+

另一个tbl_reviewlist具有以下结构的表:

+----+-------+------+------+------+
| id | entid | cola | colb | colc |
+----+-------+------+------+------+
|  1 |    12 |    N |    Y |    Y |
|  2 |    13 |    Y |    N |    Y |
|  3 |    14 |    Y |    N |    N |
+----+-------+------+------+------+

基本上,tbl_reviewlist包含有关tbl_entries. 但是,由于某些已知原因,其中的条目tbl_entries是重复的。我通过以下查询提取唯一记录:

SELECT * FROM `tbl_entries` GROUP BY `col1`, `col2`, `col3`;

tbl_entries但是,无论是否已审核,都将返回其中的任何重复行。我希望查询更喜欢那些已审查的行。我怎样才能做到这一点?

编辑:我想更喜欢已经审查过的行,但如果有尚未审查过的行,它也应该返回这些行。

提前致谢!

4

3 回答 3

2

你真的尝试过什么吗?

提示:SQL 标准要求带有group by子句的查询结果集中的每一列都必须是

  • 分组列
  • 聚合函数- ,等sum(),count()
  • 一个常数值/文字,或
  • 仅源自上述内容的表达式。

一些损坏的实现(我相信 MySQL 就是其中之一)允许包含其他列并提供它们自己的...创意...行为。如果您考虑一下,group by基本上说要执行以下操作:

  1. 按分组表达式排序此表
  2. 按顺序将其划分为基于组的子集
  3. 将每个这样的分区折叠成单行,随时计算聚合表达式。

一旦你这样做了,在折叠的组分区中要求一些不统一的东西意味着什么?

如果您有一个foo包含 A、B、C、D 和 E 列的表格,然后说类似

select A,B,C,D,E from foo group by A,B,C

根据标准,你应该得到一个编译错误。偏差实现 [通常] 将此类查询视为 [粗略] 等价于

select *
from foo t
join ( select A,B,C
       from foo
       group by A,B,C
     ) x on x.A = t.A
        and x.B = t.B
        and x.C = t.C

但是,如果不查看您正在使用的特定实现的文档,我不一定会指望这一点。

如果您想查找刚刚审核过的条目,则如下所示:

select *
from tbl_entries t
where exists ( select *
               from tbl_reviewlist x
               where x.entid = t.id
             )

会做你。但是,如果您想查找在 上重复的已审核条目,那么col1您应该这样做:col2col3

select *
from tbl_entries t
join ( select col1,col2,col3
       from tbl_entries x
       group by col1,col2,col3
       having count(*) > 1
     ) d on d.col1 = t.col1
        and d.col2 = t.col2
        and d.col3 = t.col3
where exists ( select *
               from tbl_reviewlist x
               where x.entid = t.id
             )

由于您的问题陈述相当不清楚,因此另一种看法可能是这样的:

select t.col1            ,
       t.col2            ,
       t.col3            ,
       t.duplicate_count ,
       coalesce(x.review_count,0) as review_count
from      ( select col1 ,                       
                   col2 ,                       
                   col3 ,                       
                   count(*) as duplicate_count  
            from tbl_entries
            group by col1 ,
                     col2 ,
                     col3
          ) t
left join ( select cola, colb, colc , count(*) as review_count
            from tbl_reviewList
            group by cola, colb, colc
            having count(*) > 1
          ) x on x.cola = t.col1
             and x.colb = t.col2
             and x.colc = t.col3
order by sign(coalesce(x.review_count,0)) desc ,
         t.col1 ,
         t.col2 ,
         t.col3

这个查询

  • 总结entries表格,计算存在多少次 col1/2/3 组合。
  • 总结评论表,为每个可乐/b/c 组合开发评论计数
  • 将它们连接在一起匹配 cols a:1, b:2 c:3
  • 命令他们
    • 将已审核的项目放在首位,而不是未审核的项目,
    • 然后由 col1/2/3 值。
于 2013-09-05T17:26:01.517 回答
1
SELECT e.col1, e.col2, e.col3, 
       COALESCE(MIN(r.entid), MIN(e.id)) AS id 
FROM tbl_entries AS e
  LEFT JOIN tbl_reviewlist AS r
    ON r.entid = e.id
GROUP BY e.col1, e.col2, e.col3 ;

SQL-Fiddle测试

于 2013-09-05T18:22:31.680 回答
1

我认为有一种方法可以减少重复,但这应该是一个开始:

select
  tbl_entries.ID,
  col1,
  col2,
  col3,
  cola, -- ... you get the idea ...
from (
select coalesce(min(entid), min(tbl_entries.ID)) as favID
from tbl_entries left join tbl_reviewlist on entid = tbl_entries.ID
group by col1, col2, col3
) as A join tbl_entries on tbl_entries.ID = favID
left join tbl_reviewlist on entid = tbl_entries.ID

基本上,您将所需的输出提炼为核心 ID 列表,然后重新映射回数据......

于 2013-09-05T17:57:58.077 回答