Найти строки с одинаковым идентификатором и иметь определенный набор имен - PullRequest
1 голос
/ 27 декабря 2011

EDIT:

У меня есть таблица с 3 строками, как это.

ID    NAME REV
1     A    0
1     B    0
1     C    0
2     A    1
2     B    0
2     C    0
3     A    1
3     B    1

Я хочу найти идентификатор, у которого есть определенный набор Имен и REV такой же пример: Edit2: решение GBN работало бы отлично, но у меня нет доступа для создания новых таблиц. Дополнительным ограничением является невозможность создания новых таблиц.

if input = A,B then output is 3
if input = A ,B,C then output is 1 and not 1,2 since the rev level differs in 2.

Ответы [ 3 ]

5 голосов
/ 27 декабря 2011

Самый простой способ - сравнить COUNT для идентификатора с количеством элементов в вашем списке:

SELECT
   ID
FROM
   MyTable
WHERE
   NAME IN ('A', 'B', 'C')
GROUP BY
   ID
HAVING
   COUNT(*) = 3;

Примечание: ORDER BY не требуется и идет после ХАВИНГА, если необходимо

Редактировать, с обновлением вопроса. В MySQL проще использовать отдельную таблицу для поисковых запросов

DROP TABLE IF EXISTS gbn;
CREATE TABLE gbn (ID INT, `name` VARCHAR(100), REV INT);
INSERT gbn VALUES (1, 'A', 0);
INSERT gbn VALUES (1, 'B', 0);
INSERT gbn VALUES (1, 'C', 0);
INSERT gbn VALUES (2, 'A', 1);
INSERT gbn VALUES (2, 'B', 0);
INSERT gbn VALUES (2, 'C', 0);
INSERT gbn VALUES (3, 'A', 0);
INSERT gbn VALUES (3, 'B', 0);

DROP TABLE IF EXISTS gbn1;
CREATE TABLE gbn1 ( `name` VARCHAR(100));
INSERT gbn1 VALUES ('A');
INSERT gbn1 VALUES ('B');

SELECT
   gbn.ID
FROM
   gbn
   LEFT JOIN
   gbn1 ON gbn.`name` = gbn1.`name`
GROUP BY
   gbn.ID
HAVING
   COUNT(*) = (SELECT COUNT(*) FROM gbn1)
   AND MIN(gbn.REV) = MAX(gbn.REV);

INSERT gbn1 VALUES ('C');

SELECT
   gbn.ID
FROM
   gbn
   LEFT JOIN
   gbn1 ON gbn.`name` = gbn1.`name`
GROUP BY
   gbn.ID
HAVING
   COUNT(*) = (SELECT COUNT(*) FROM gbn1)
   AND MIN(gbn.REV) = MAX(gbn.REV);

Изменить 2, без дополнительной таблицы, использовать производную (встроенную) таблицу:

SELECT
   gbn.ID
FROM
   gbn
   LEFT JOIN
   (SELECT 'A' AS `name`
    UNION ALL SELECT 'B' 
    UNION ALL SELECT 'C'
   ) gbn1 ON gbn.`name` = gbn1.`name`
GROUP BY
   gbn.ID
HAVING
   COUNT(*) = 3 -- matches number of elements in gbn1 derived table
   AND MIN(gbn.REV) = MAX(gbn.REV);
1 голос
/ 28 декабря 2011

Ладно! ... Я решил свою проблему!Я изменил логику GBN, чтобы сделать это без таблицы поиска, используя условие IN *

1, при выполнении MAX (rev) = MIN (REV): если у меня есть такие данные.

ID    NAME   REV
1     A      0
1     B      1
1     A      1

тогда, когда я использую запрос типа

Select ID from TABLE
where NAME in {A,B}
groupby ID
having count(*) = 2
and MIN(REV) = MAX(REV)

, он не покажет мне идентификатор 1, так как минимальное и максимальное значения различаются, а количество равно 3.

Так что я просто добавляю еще один столбец в группу

, чтобы окончательный запрос был

Select ID from TABLE
where NAME in {A,B}
groupby ID,REV
having count(*) = 2
and MIN(REV) = MAX(REV)

Спасибо, всем, кто помог.!

1 голос
/ 27 декабря 2011

Аналогично gbn, но допускает возможность дублирования комбинаций ID / Имя:

SELECT ID
FROM MyTable
WHERE NAME IN ('A', 'B', 'C')
GROUP BY ID
HAVING COUNT(DISTINCT NAME) = 3;
...