Я хочу написать SQL-запрос для нескольких столбцов с условиями. таблица выглядит так:
ID Company User
1 Bov LPF
2 Ak LPF
3 Bov LPF
4 Bov ABC
5 Ak ABC
6 ZP ABC
7 REP ABC
8 REP CDE
9 KEK CDE
10 Ak CDE
11 PER CDE
12 Bov BKE
Результат должен быть таким:
Ожидаемый результат например:
ID Company User
1 Bov LPF
2 Ak LPF
3 Bov LPF
4 Bov ABC
5 Ak ABC
7 REP ABC
8 REP CDE
10 Ak CDE
11 PER CDE
Как мне написать запрос?
Обновлять:
Я думал о таком запросе, но он не дал мне правильных результатов:
select *
from
(
select *,row_number() over(partition by user,company order by user, company) as row, ROW_NUMBER() over(order by newid()) as total
from
(
select *
from
(
select *, 0 as Bov, sum(iif (Company= 'Ak',1,0)) over (order by newid()) as Ak
FROM table a
where Company = 'Ak'
) as eu
where eu.Ak <= 2
UNION ALL
select *
from
(
select *, sum(iif (company = 'Bov',1,0)) over (order by newid() ) as Bov, 0 as Ak
FROM table a
where Company = 'Bov'
) as nn
where nn.Bov <= 2
UNION ALL
select *, 0 as Bov, 0 as Ak
FROM table a
where Company not in ('Bov','Ak')
) as z
) as z1
where z1.row <= 3
and z1.total <= 9
Фильтр <= 2 предназначен для компании, которая должна возвращать минимум два раза в результате
Фильтр row <= 3 предназначен для трех строк на пользователя.
Фильтр total <= 9 предназначен для общего количества строк, которое должно быть 9.
В этом запросе я не уверен, что у меня есть хотя бы две строки для компаний Bov, Ak и REP.
Начнем с select. Если у вас есть вопрос конкретный, опубликуйте его со всеми применимыми деталями. Прочтите это, чтобы получить несколько советов по улучшению вашего следующего вопроса.


select *
from table
group by id
having count(User) <= 3
order by id
Это то, что тебе надо?
Спасибо за ваш ответ, но это не то, что я хочу, потому что в моем результате мне нужно для каждого пользователя три строки (пользователи с менее чем тремя строками могут быть пропущены, для пользователей с более чем тремя строками он должен случайным образом выбрать три ряды). Рядом с этим мне также нужны две строки для компании Bov, REP и Ak в результате (две строки с компанией Bov, две строки с REP и две строки с Ak).
Вы можете использовать это.
DECLARE @MyTable TABLE (ID INT, Company VARCHAR(10), [User] VARCHAR(10))
INSERT INTO @MyTable VALUES
(1 , 'Bov', 'LPF'),
(2 , 'Ak ', 'LPF'),
(3 , 'Bov', 'LPF'),
(4 , 'Bov', 'ABC'),
(5 , 'Ak ', 'ABC'),
(6 , 'ZP ', 'ABC'),
(7 , 'REP', 'ABC'),
(8 , 'REP', 'CDE'),
(9 , 'KEK', 'CDE'),
(10 , 'Ak ', 'CDE'),
(11 , 'PER', 'CDE'),
(12 , 'Bov', 'BKE')
SELECT ID, Company, [User] FROM
( SELECT *
, ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY (CASE WHEN Company IN ('Bov','REP','Ak') THEN 0 ELSE 1 END) ) RN
, COUNT(*) OVER (PARTITION BY [User]) CmpCnt
, COUNT(CASE WHEN Company IN ('Bov','REP','Ak') THEN 1 END) OVER (PARTITION BY [User]) PriCmpCnt
FROM @MyTable
) T
WHERE
T.CmpCnt > 2
and T.PriCmpCnt > 1
and T.RN < 4
order by ID
Результат:
ID Company User
----------- ---------- ----------
1 Bov LPF
2 Ak LPF
3 Bov LPF
4 Bov ABC
5 Ak ABC
7 REP ABC
8 REP CDE
10 Ak CDE
11 PER CDE
Вот как я подхожу к этому; см. комментарии для объяснения / дайте мне знать, если вам нужна дополнительная информация, чтобы что-то понять ...
;with cte as
(
select Id
, Company
, [User]
, Row_Number() over (partition by [User] order by randomOrder) PerUserRowNum
, case
when Company in ('BOV','REP', 'AK') then
case
when Row_Number() over (partition by Company order by randomOrder) <= 2 then 1
else 0
end
else 0
end MustInclude
from (select *, newid() randomOrder from SourceData) x
)
select top 9 --total rows is 9
Id, Company, [User]
from cte
where PerUserRowNum <= 3 --show 3 rows per user
and [User] in ( --only the users with at least three rows will be in the result
select [User]
from cte
where PerUserRowNum = 3
)
order by MustInclude desc, newid() --ensure all the stuff we must include is returned, then make up the rest of the results with whatever
Привет, JohnLBevan, спасибо за ваш ответ, но он не дает мне правильного ответа. Когда я использую временную таблицу, как мы используем в других комментариях, я не получаю трех строк для каждого пользователя, которого я хочу. Я также получаю BKE в результатах (его только один раз в исходной таблице).
Извинения; пропустил скобки на поле User. Поскольку User является ключевым словом, он должен быть [User], чтобы гарантировать, что он возвращает значение столбца вместо текущей схемы. Чтобы избежать таких проблем, я стараюсь избегать использования ключевых слов в качестве имен столбцов. Сейчас исправлено: sqlfiddle.com/#!18/a7b88/2
Спасибо, теперь три строки на пользователя идеальны. Но я не всегда получаю две строки для каждой компании (Bov, REP и Ak).
Ах, прости @Ray; поскольку newid() генерировался каждый раз, он не работал с функцией row_number(); Я внес поправки, чтобы сначала возвращать идентификаторы, а затем использовать их для определения последовательности. Надеюсь, что теперь игра идет хорошо.
я все еще не получаю две строки для каждой компании с вашим новым запросом: sqlfiddle.com/#!18/a7b88/8
Ах, извините; похоже, что логика, ограничивающая нас до 3 пользователей, удаляет некоторые записи, в которых эти компании «должны включать» ... думаю, что лучшим решением будет выполнение логики компании в первоначальном запросе, а затем ограничение пользователей в более позднем запросе , отдавая приоритет тем, которые помечены как "должны включать" ... немного поиграют, но сейчас у них нет шансов ...
Это ОЧЕНЬ похоже на домашнее задание. Нужно хотя бы попробовать.