SQL - объединение нескольких таблиц и выбор первой записи по условиям - PullRequest
2 голосов
/ 11 апреля 2011

У меня есть следующие таблицы:

Projects (ID, Name, ManagerUser_ID)
Users(ID, Name, Active)
Delegates(ProjectID, UserID, OrderNo)

ManagerUser_ID - менеджер проекта для проекта и ссылка на таблицу пользователей. Пользователи, однако, могут быть Inactive. Таким образом, таблица «Делегаты» является таблицей «многие ко многим», определяющей пользователей, которые могут получить доступ к данным проекта.

Что мне нужно, так это выбрать первого делегата для проекта, который является Active при условии, что менеджер Inactive. Поле OrderNo указывает порядок делегатов (1 - первый).

Некоторые примеры данных:

Project
1, Project1, 2
2, Project2, 4
3, Project3, 1

Users
1, Joe, true
2, John, false
3, Dave, true
4, Bob, false

Delegates
1, 4, 1
1, 1, 2
1, 3, 3
2, 2, 1
2, 4, 2
2, 3, 3

Таким образом, вывод моего запроса должен показать:

Project1, Joe
Project2, Dave
Project3, Joe

Показать проекты и пользователей для каждого проекта, где, если ManagerUser_ID неактивен, то выберите User в Delegates с самым низким OrderNo, то есть Active.

Ответы [ 4 ]

1 голос
/ 11 апреля 2011

Это, кажется, делает трюк (используя оконную функцию)

SELECT  P.Name, ISNULL(U.Name, FirstDelegate.Name) AS ProjManager
FROM    Projects P LEFT OUTER JOIN
        Users U ON P.ManagerUser_ID = U.ID AND U.Active = 1 LEFT OUTER JOIN
        (
            SELECT * FROM
            (
                SELECT D.ProjectID, 
                       US.Name, 
                       ROW_NUMBER() OVER (PARTITION BY ProjectID ORDER BY OrderNo) AS SeqNo
                FROM  Delegates D INNER JOIN
                      Users US ON D.UserID = US.ID
                WHERE US.Active = 1
            ) AS Del
            WHERE Del.SeqNo = 1
        ) AS FirstDelegate ON P.ID = FirstDelegate.ProjectID
1 голос
/ 11 апреля 2011

Я думаю, что это будет примерно так.Идея состоит в том, чтобы сделать дополнительное соединение (используя левое соединение), чтобы найти более раннюю допустимую строку.Если вы можете найти эту строку, то, очевидно, текущая строимая строка не та, которую вы хотите:

select p.Name,m.Name from Projects p inner join Users m on p.ManagerUser_ID = m.ID and m.Active = 1
union all
select
    p.Name,
    u.Name
from
    Projects p
        inner join
    Delegates d
        on
            p.ID = d.ProjectID
        inner join
    Users u
        on
            d.UserID = u.ID and
            u.Active = 1
        left join
    Delegates d_anti
        inner join
    Users u_anti
        on
            d_anti.UserID = u_anti.ID and
            u_anti.Active = 1
        on
            p.ID = d_anti.ProjectID and
            d_anti.OrderNo < d.OrderNo
where
    u_anti.ID is null
1 голос
/ 11 апреля 2011
Select projectName, userName
From

(
    Select projectName, userName, row_number() over (partition by projectName order by priority ASC) as rank
    From
    (
        SELECT p.name as projectName, u.name as userName, 1 as priority
        FROM projects p INNER JOIN users u ON u.active = true and u.id = p.ManagerUser_ID

        UNION

        SELECT TOP(1) p.name, u.name, 2
        FROM Delegates d INNER JOIN projects p  ON p.id = d.projectId
                         INNER JOIN users u ON u.id = d.userId
        Where u.active = true
        Order by u.OrderNo ASC
    )
)
where rank = 1
0 голосов
/ 11 апреля 2011
select p.name, 
u.name, 
min(d.orderNo)
from projects p, 
users u, 
users manager, 
delegates d
where p.ManagerUser_ID = manager.id
and manager.active = false
and p.id = d.projectId
and d.userid = u.id
group by p.name, 
u.name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...