如何根据sql中的条件选择组中的行?

ct2axkht  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(271)

问题请考虑下表:

+--------------+--------+--------+
| transactionID | Sgroup | Rgroup |
+--------------+--------+--------+
|            1 | A      | I      |
|            1 | A      | J      |
|            2 | B      | B      |
|            2 | B      | K      |
+--------------+--------+--------+

对于每个 transactionID (2行与id 1关联,2行与id 2关联)我要选择 Sgroup = Rgroup ,如果 transactionID 满足条件。否则,我想随机选择一行。对于每个 transactionID 最多一行 Sgroup = Rgroup . 我该怎么做?
尝试的解决方案我知道如何选择符合条件的行 Sgroup = Rgroup 具体如下:

SELECT *
FROM Transaction 
WHERE Sgroup = Rgroup;

+---------------+--------+--------+
| transactionID | Sgroup | Rgroup |
+---------------+--------+--------+
|             2 | B      | B      |
+---------------+--------+--------+

我还知道如果条件不满足以下条件,如何随机选择一行(由于这个问题):

SELECT * FROM
(SELECT *
FROM Transaction
WHERE NOT transactionID IN
(SELECT transactionID
FROM Transaction 
WHERE Sgroup = Rgroup)
ORDER BY RAND()) AS temp
GROUP BY temp.transactionID;

+---------------+--------+--------+
| transactionID | Sgroup | Rgroup |
+---------------+--------+--------+
|             1 | A      | I      |
+---------------+--------+--------+

如何将这两个表达式组合成一个表达式?我试着用一个case表达式,但没走多远。有人能提出解决办法吗?
下面的示例代码是生成表的代码:

CREATE DATABASE MinimalExample;
USE MinimalExample;

CREATE TABLE Transaction (
transactionID int,
Sgroup nvarchar(1),
Rgroup nvarchar(1)
);

INSERT INTO Transaction VALUES
(1,'A','I'), 
(1,'A','J'),
(2,'B','B'),
(2,'B','K');
sr4lhrrt

sr4lhrrt1#

我认为变量可能是最简单的解决方案,如果你真的是指“随机”:

select t.*
from (select t.*,
             (@rn := if(@i = transactionID, @rn + 1,
                        if(@i := transactionID, 1, 1)
                       )
             ) as rn
      from (select t.*
            from t
            order by transactionID, (sgroup = rgroup) desc, rand()
           ) t cross join
           (select @i := -1, @rn := 0) params
     ) t
where rn = 1;

如果你所说的“随机”是指“任意”,你可以使用这个快速而肮脏的伎俩:

(select t.*
 from t
 where sgroup = rgroup
)
union all
(select t.*
 from t
 where not exists (select 1 from t t2 where t2.id = t.id and t2.sgroup = t2.rgroup)
 group by transactionID
);

它使用可怕的 select *group by ,我强烈反对在几乎所有情况下使用。但是,在本例中,您特别尝试将每个组减少到一个不确定的行,因此看起来并不是很糟糕。我要注意的是,mysql不能保证结果集中的列都来自同一行,尽管实际上它们来自同一行。
最后,如果每行都有一个唯一的主键,则可以使用最简单的解决方案:

select t.*
from t
where t.id = (select t2.id
              from t t2
              where t2.transactionID = t.transactionID
              order by (rgroup = sgroup) desc, rand()
             );

相关问题