Вывести всех клиентов, у которых в поле type есть значения и 1 и 2

Есть таблица tmp с полями num, fio, service, type.

В поле service могут быть значения: Сборка ПК со скидкой, Сборка ПК, Ремонт ПК, Ремонт ПК со скидкой В поле type могут быть значения 1 и 2.

Для Сборка ПК со скидкой, Сборка ПК оно 1 Для Ремонт ПК, Ремонт ПК со скидкой оно 2

Нужно получить все записи (клиентов), которым делались услуги с type 1 и 2, т.е. оба типа услуг.

введите сюда описание изображения


Ответы (4 шт):

Автор решения: CrazyElf

Может вот так, например, отобрать fio. А дальше можно и записи все по fio отобрать.

select distinct f.fio from tmp f
join tmp t1 on t1.fio = f.fio and t1.type = 1
join tmp t2 on t2.fio = f.fio and t2.type = 2

Или так:

select distinct t1.fio from tmp t1
join tmp t2 on t2.fio = t1.fio
where t1.type = 1 and t2.type = 2
→ Ссылка
Автор решения: Sergei Kirjanov

может GROUP_CONCAT(type SEPARATOR ' ') ... GROUP BY fio, а потом уже из него LIKE

→ Ссылка
Автор решения: Yitzhak Khabinsky

Вот как это сделать в MS SQL Server.

Алгоритм очень прост.

(1) Счетчик количества услуг обоих типов для клиента в каждой записи внутри CTE. Таким образом, мы получаем поля TotalType1 и TotalType2.

(2) Второй SELECT проверяет наличие обоих типов услуг. И отфильтровывает записи, когда это не так через предложение WHERE TotalType1 > 0 AND TotalType2 > 0

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, num INT, fio NVARCHAR(20), [service] NVARCHAR(30), [type] INT);
INSERT INTO @tbl (num, fio, [service], [type])
VALUES
(444, N'Иванов', N'Сборка ПК', 1),
(444, N'Иванов', N'Сборка ПК со скидкой', 1),
(444, N'Иванов', N'Ремонт ПК', 2),
(444, N'Иванов', N'Ремонт ПК со скидкой', 2),
(445, N'Петров', N'Сборка ПК со скидкой', 1),
(445, N'Петров', N'Ремонт ПК', 2),
(555, N'Васильев', N'Ремонт ПК', 2),
(332, N'Михайлов', N'Сборка ПК', 1);
-- DDL and sample data population, end

;WITH rs AS
(
    SELECT *
        , SUM(IIF(type=1,1,0)) OVER (PARTITION BY num) AS TotalType1
        , SUM(IIF(type=2,1,0)) OVER (PARTITION BY num) AS TotalType2
    FROM @tbl
)
SELECT * 
FROM rs
WHERE TotalType1 > 0 AND TotalType2 > 0
ORDER BY ID;

Вывод

+----+-----+--------+----------------------+------+------------+------------+
| ID | num |  fio   |       service        | type | TotalType1 | TotalType2 |
+----+-----+--------+----------------------+------+------------+------------+
|  1 | 444 | Иванов | Сборка ПК            |    1 |          2 |          2 |
|  2 | 444 | Иванов | Сборка ПК со скидкой |    1 |          2 |          2 |
|  3 | 444 | Иванов | Ремонт ПК            |    2 |          2 |          2 |
|  4 | 444 | Иванов | Ремонт ПК со скидкой |    2 |          2 |          2 |
|  5 | 445 | Петров | Сборка ПК со скидкой |    1 |          1 |          1 |
|  6 | 445 | Петров | Ремонт ПК            |    2 |          1 |          1 |
+----+-----+--------+----------------------+------+------------+------------+

FoxPro SQL

SELECT a.* FROM @tbl AS a
    INNER JOIN 
(SELECT num
    , SUM(IIF(type=1,1,0)) AS TotalType1
    , SUM(IIF(type=2,1,0)) AS TotalType2
FROM @tbl
GROUP BY num
HAVING SUM(IIF(type=1,1,0)) > 0 AND SUM(IIF(type=2,1,0)) > 0) AS b
    ON a.num = b.num
→ Ссылка
Автор решения: Akina
SELECT fio
FROM tmp
WHERE type IN (1, 2)
GROUP BY fio
HAVING COUNT(DISTINCT type) = 2;

fiddle

→ Ссылка