想象一下下表:
| my_id | my_status | my_title | my_desc |
|-------|-----------|-----------------|-----------------------|
| 1 | N | Hello World | This is a description |
| 2 | N | Hello again | Blah blah |
| 3 | N | This is fun | I like StackExchange |
| 3 | E | This edited fun | I love StackExchange |
| 4 | N | Goodbye | Last record here. |
正常记录的my_status列中有"N"。当一个条目被编辑时,我创建了一个标有"E"的新记录。一旦编辑被批准,我就会删除原始的N记录,并将E记录更新为N记录。它基本上是一个编辑审批系统。
现在,我想查询该表,并显示具有唯一id的记录,这些记录标记为"E"(如果存在(,否则返回标准的"N"记录。所以最终的结果应该是:
| my_id | my_status | my_title | my_desc |
|-------|-----------|-----------------|-----------------------|
| 1 | N | Hello World | This is a description |
| 2 | N | Hello again | Blah blah |
| 3 | E | This edited fun | I love StackExchange |
| 4 | N | Goodbye | Last record here. |
我确信这在一个问题中一定是可能的,但它现在正在躲避我。(现在是星期五下午,办公室里的温度是33度,我的大脑都快融化了(。
我在想象类似的东西
SELECT * FROM my_table WHERE IF EXISTS (my_status='E') ELSE (my_status='N')
(我知道这不是有效的SQL,但希望它能指明我想要实现的要点(。
SQL Fiddle在这里:http://sqlfiddle.com/#!9/1b049/1
您可以按id分组,然后为每个id 取最小状态('N'大于'E'(
select t1.*
from my_table t1
join
(
SELECT my_id, min(my_status) as status
FROM my_table
GROUP BY my_id
) t2 on t1.my_id = t2.my_id and t1.my_status = t2.status
SQLFiddle演示
一个可能的解决方案是确保不存在任何具有相同my_id和my_status='E'的行:
SELECT * FROM my_table t
where not (my_status = 'N' and exists (
select 1 from my_table where my_id = t.my_id
and my_status = 'E')
)
SQL Fiddle
我认为一个简单的方法是使用union all
:
select f.*
from following f
where f.status = 'E'
union all
select f.*
from following f
where not exists (select 1
from following f2
where f2.my_id = f.my_id and f2.status = 'E'
);
第一个子查询获取所有的E
s。第二个子查询获取没有相应E
的所有N
s。使用status
和my_id, status
上的索引,性能应该非常好。
分组依据和MIN函数(由于'E'<'N'(:
SELECT my_id, MIN(my_status), my_title, my_desc FROM my_table group by my_id
远不如于尔根的答案优雅:
SELECT * FROM my_table AS t
INNER JOIN (SELECT my_id, COUNT(*) AS cnt FROM my_table GROUP BY 1) AS t2
ON t.my_id = t2.my_id
WHERE my_status = "E" OR t2.cnt = 1;
这基本上意味着说"如果它是一个‘E’,否则,检查是否只有一行带有这个my_id,如果是,则意味着只有一个‘N’行"。