使用GROUP_CONCAT作为输入选择WHERE IN

时间:2017-12-07 07:04:16

标签: php mysql select group-concat where-in

请在继续之前阅读此内容:Filter an unfiltered table against a whitelist table

所以,我目前有一个白名单表设置,如引用的链接所示,我遇到了由该表提出的另一个问题,即检查每列的UNIQUENESS。作为MySQL的规范,不可能将NULL列设置为UNIQUE,因此,我决定采用不同的解决方案来检查行是否重复,方法是使用SELECT GROUP BY查询,如下所示。

SELECT GROUP_CONCAT(ID) AS IDs, country, region, item, count(*) AS amount
FROM whitelist

现在,为了检查项目是否重复,我已将其在另一层之上变形。

SELECT IDs, country, region, item, amount
FROM (SELECT GROUP_CONCAT(ID) AS IDs, country, region, item, count(*) AS amount
      FROM whitelist) tmp
WHERE amount > 1

仍然按预期正常工作,但问题从这里开始。

我是否可以使用此数据,并重新选择白名单表,以便我可以将每个条目作为一行添加类似......

SELECT ID, country, region, item
FROM whitelist
WHERE ID IN (SELECT group_concat(ID)
               FROM (SELECT group_concat(ID) AS ID, country, region, item, COUNT(*) AS AMOUNT
                       FROM whitelist
                      GROUP BY country, region, item) tmp
              WHERE AMOUNT > 1)

当然,我可以使用PHP并爆炸group_concat ID并重新选择它,但我想知道是否可以在一个SQL查询调用而不是两个中执行它。

编辑:哎呀,上面的示例中有一个错误(意外地使用了真实架构xD)

Edit2: Doh,我突然想到为什么会让事情变得复杂,为什么不只是简单地使用它......

SELECT wl1.ID, wl1.country, wl1.region, wl1.item, wl1.reason
  FROM whitelist wl1, 
       (SELECT country, region, item
          FROM whitelist
         GROUP BY country, region, item
        HAVING count(*) > 1) wl2
 WHERE wl1.country = wl2.country AND
       wl1.region = wl2.region AND
       wl1.item = wl2.reason

...但仍然失败,因为你不能在两个NULL列上使用=。呃,到目前为止如此接近>。<

致: Bill Karwin

这正是这里的问题。如果我在country,region,item上设置了一个唯一键,并且我执行以下SQL,则会发生这种情况。

INSERT INTO whitelist(country, region, item) VALUES ('Taiwan', 'Asia', 'PC');
INSERT INTO whitelist(country, region, item) VALUES ('Taiwan', 'Asia', 'PC');
-- Would fail due to UNIQUE check

但是,如果我包含任何通配符,即NULL,则会发生这种情况。

INSERT INTO whitelist(country, region, item) VALUES (NULL, 'Asia', 'Rice');
INSERT INTO whitelist(country, region, item) VALUES (NULL, 'Asia', 'Rice');
-- Would succeed due to UNIQUE does not check NULL columns.

因此,这篇文章的想法是列出列表中的所有重复白名单,以便运营商可以决定要保留什么和删除什么。

1 个答案:

答案 0 :(得分:1)

不热衷于这个解决方案,但可行: -

SELECT a.ID, 
        a.country, 
        a.region, 
        a.item
FROM whitelist a
INNER JOIN 
(
    SELECT group_concat(ID) AS ID, USERNAME, COMPNAME, PUBLISHER, NAME, VERSION, COUNT(*) AS AMOUNT
    FROM software_checklist
    GROUP BY USERNAME, COMPNAME, PUBLISHER, NAME, VERSION 
    HAVING AMOUNT > 1
) tmp
ON FIND_IN_SET(a.ID, tmp.ID)