SQL-запрос с условиями для аудита

Я хочу написать 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

Результат должен быть таким:

  • Дайте мне по три строки на пользователя (в результате будут только пользователи, у которых не менее трех строк).
  • Компании Бов, РЭП и Ак должны вернуться как минимум два раза в результат
  • Это для аудита, поэтому все должно быть упорядочено случайным образом (например, по newid ())
  • Всего строк 9.

Ожидаемый результат например:

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.

Это ОЧЕНЬ похоже на домашнее задание. Нужно хотя бы попробовать.

Sean Lange 31.07.2018 18:58

Начнем с select. Если у вас есть вопрос конкретный, опубликуйте его со всеми применимыми деталями. Прочтите это, чтобы получить несколько советов по улучшению вашего следующего вопроса.

HABO 31.07.2018 19:26
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
2
89
3

Ответы 3

 select *
 from table
 group by id
 having count(User) <= 3
 order by id

Это то, что тебе надо?

Спасибо за ваш ответ, но это не то, что я хочу, потому что в моем результате мне нужно для каждого пользователя три строки (пользователи с менее чем тремя строками могут быть пропущены, для пользователей с более чем тремя строками он должен случайным образом выбрать три ряды). Рядом с этим мне также нужны две строки для компании Bov, REP и Ak в результате (две строки с компанией Bov, две строки с REP и две строки с Ak).

Ray 31.07.2018 20:02

Вы можете использовать это.

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

Вот как я подхожу к этому; см. комментарии для объяснения / дайте мне знать, если вам нужна дополнительная информация, чтобы что-то понять ...

Демонстрация SQL Fiddle

;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 в результатах (его только один раз в исходной таблице).

Ray 01.08.2018 12:05

Извинения; пропустил скобки на поле User. Поскольку User является ключевым словом, он должен быть [User], чтобы гарантировать, что он возвращает значение столбца вместо текущей схемы. Чтобы избежать таких проблем, я стараюсь избегать использования ключевых слов в качестве имен столбцов. Сейчас исправлено: sqlfiddle.com/#!18/a7b88/2

JohnLBevan 01.08.2018 12:28

Спасибо, теперь три строки на пользователя идеальны. Но я не всегда получаю две строки для каждой компании (Bov, REP и Ak).

Ray 01.08.2018 13:39

Ах, прости @Ray; поскольку newid() генерировался каждый раз, он не работал с функцией row_number(); Я внес поправки, чтобы сначала возвращать идентификаторы, а затем использовать их для определения последовательности. Надеюсь, что теперь игра идет хорошо.

JohnLBevan 01.08.2018 13:57

я все еще не получаю две строки для каждой компании с вашим новым запросом: sqlfiddle.com/#!18/a7b88/8

Ray 01.08.2018 14:30

Ах, извините; похоже, что логика, ограничивающая нас до 3 пользователей, удаляет некоторые записи, в которых эти компании «должны включать» ... думаю, что лучшим решением будет выполнение логики компании в первоначальном запросе, а затем ограничение пользователей в более позднем запросе , отдавая приоритет тем, которые помечены как "должны включать" ... немного поиграют, но сейчас у них нет шансов ...

JohnLBevan 01.08.2018 16:15

Другие вопросы по теме