Mysql从具有三个条件之一的组中选择一条记录

时间:2017-06-06 17:11:34

标签: mysql sql

使用MySQL。我需要根据以下条件为每组storeID + profitCenter提取一条记录:

1)如果组有一个活动记录(active = 1),请选择该记录

2)如果组没有活动记录,请选择最近的(max(id))

3)如果组有多个活动记录,请选择最近的活动记录

样本表: (为清晰起见,添加了空白行)

 ID  | storeID | profitCenter | active
 --------------------------------------
 1   | X       | 1            |    1
 2   | X       | 1            |    0
 3   | X       | 1            |    0

 4   | X       | 2            |    0
 5   | X       | 2            |    1

 6   | X       | 3            |    0
 7   | X       | 3            |    0
 8   | X       | 3            |    0

 9   | X       | 4            |    1
10   | X       | 4            |    1
11   | X       | 4            |    0

12   | X       | 5            |    1

13   | X       | 6            |    0

期望的结果:

 ID  | storeID | profitCenter | active
------------------------------------------ 
 1   | X       | 1            |    1
 5   | X       | 2            |    1
 8   | X       | 3            |    0
10   | X       | 4            |    1
12   | X       | 5            |    1
13   | X       | 6            |    0

单个查询会很棒,但我认为由于其复杂性,我需要在存储过程中执行此操作。我需要将记录写入新表,以便我可以在连接中使用它等。到目前为止,我真正得到的只是......

...一个简单的查询来拉动"单个"这样的记录....

 SELECT * FROM table GROUP BY storeID, profitCenter HAVING count(*) = 1 AND active = 1
UNION
SELECT * FROM table GROUP BY storeID, profitCenter HAVING count(*) = 1 AND active = 0

......产生......

 ID  | storeID | profitCenter | active
------------------------------------------ 
12   | X       | 5            |    1
13   | X       | 6            |    0

然后我可以做......

 SELECT sum(active),tmult.* FROM
      (SELECT t.* FROM t LEFT JOIN
           (SELECT t.* FROM t GROUP BY storeID, profitCenter HAVING count(*) = 1 AND active = 1
      UNION
           SELECT t.* FROM t GROUP BY storeID, profitCenter HAVING count(*) = 1 AND active = 0) tsing
      ON t.id = tsing.id
      WHERE tsing.id IS NULL) tmult
 GROUP BY storeid, profitCenter
 HAVING sum(active)=1;

...为每个只有一条活动记录的组提供活动记录:

 ID  | storeID | profitCenter | active
 --------------------------------------
 1   | X       | 1            |    1
 5   | X       | 2            |    1

没有活动记录或多个活动记录的群组我甚至无法开始弄明白。

我采取了正确的方法吗?我应该在SQL中尝试这个吗?我可以写一个脚本来做,但我希望不必走这条路。

任何建议都将受到赞赏。

2 个答案:

答案 0 :(得分:1)

我相信这样的事情应该这样做:

 select 
    ifnull(max(active_records.id), max(all_records.id)) id,
    all_records.store_id,
    all_records.profit_center,
    if(max(active_records.id) is null, 0, 1) active
from
    store all_records
    left outer join store active_records on all_records.id = active_records.id and active_records.active = 1
group by
    all_records.store_id,
    all_records.profit_center
;

ddl和insert的完整示例如下所示:

create table store (
    id int,
    store_id varchar(64),
    profit_center int,
    active bit
);

insert into store values ( 1   , 'X'       , 1            ,    1);
insert into store values ( 2   , 'X'       , 1            ,    0);
insert into store values ( 3   , 'X'       , 1            ,    0);
insert into store values ( 4   , 'X'       , 2            ,    0);
insert into store values ( 5   , 'X'       , 2            ,    1);
insert into store values ( 6   , 'X'       , 3            ,    0);
insert into store values ( 7   , 'X'       , 3            ,    0);
insert into store values ( 8   , 'X'       , 3            ,    0);
insert into store values ( 9   , 'X'       , 4            ,    1);
insert into store values (10   , 'X'       , 4            ,    1);
insert into store values (11   , 'X'       , 4            ,    0);
insert into store values (12   , 'X'       , 5            ,    1);
insert into store values (13   , 'X'       , 6            ,    0);

select 
    ifnull(max(active_records.id), max(all_records.id)) id,
    all_records.store_id,
    all_records.profit_center,
    if(max(active_records.id) is null, 0, 1) active
from
    store all_records
    left outer join store active_records on all_records.id = active_records.id and active_records.active = 1
group by
    all_records.store_id,
    all_records.profit_center
;

+ ------- + ------------- + ------------------ + ----------- +
| id      | store_id      | profit_center      | active      |
+ ------- + ------------- + ------------------ + ----------- +
| 1       | X             | 1                  | 1           |
| 5       | X             | 2                  | 1           |
| 8       | X             | 3                  | 0           |
| 10      | X             | 4                  | 1           |
| 12      | X             | 5                  | 1           |
| 13      | X             | 6                  | 0           |
+ ------- + ------------- + ------------------ + ----------- +
6 rows

答案 1 :(得分:0)

您可以使用union all尝试此操作。

SELECT * 
FROM TABLE
WHERE (storeID, profitCenter, Id) IN (
SELECT storeID, profitCenter, MAX(case when active=1 then id end) as maxid
FROM table 
GROUP BY storeID, profitCenter
HAVING SUM(active) >= 1
UNION ALL
SELECT storeID, profitCenter, MAX(id)
FROM table 
GROUP BY storeID, profitCenter
HAVING SUM(active) = 0
)