chamindat Ответов: 1

Как выбрать одну строку из нескольких строк в SQL


У меня есть образец таблицы :
Access_Id  Access_LoginTimeStamp    Access_Status
1150080    23/08/2020 21:30:57 PM   Login
1150080	   23/08/2020 21:31:57 PM   Logout
1150080	   23/08/2020 21:32:57 PM   Login
1150080    23/08/2020 21:33:58 PM   Logout
1150083	   23/08/2020 21:35:58 PM   Login
1150084	   23/08/2020 21:41:31 PM   Login
1150084	   23/08/2020 21:41:49 PM   Logout

Я хочу, чтобы результирующий набор был таким:
Access_Id  Access_LoginTimeStamp   Access_Status Access_LogoutTimeStamp  Access_Status
1150080    23/08/2020 21:30:57 PM  Login         23/08/2020 21:31:57 PM  Logout
1150080	   23/08/2020 21:32:57 PM  Login         23/08/2020 21:33:58 PM  Logout
1150083	   23/08/2020 21:35:58 PM  Login         -                       -
1150084	   23/08/2020 21:41:31 PM  Login         23/08/2020 21:41:49 PM  Logout


Что я уже пробовал:

Есть ли какой - нибудь способ добиться этого в SQL? это срочно. Любая помощь действительно ценится.

Спасибо.

Jörgen Andersson

Да, вы можете достичь этого, используя комбинацию "островов и промежутков" и разворота.
Там у вас есть ваши условия поиска. У меня есть другие, более срочные дела.

1 Ответов

Рейтинг:
2

Richard Deeming

Попробуйте что-нибудь вроде этого:

WITH cte As
(
    SELECT
        Access_Id,
        Access_LoginTimeStamp,
        Access_Status,
        ROW_NUMBER() OVER (PARTITION BY Access_Id ORDER BY Access_LoginTimeStamp) As RN
    FROM
        YourTable
)
SELECT
    IsNull(LI.Access_Id, LO.Access_Id) As Access_Id,
    LI.Access_LoginTimeStamp,
    LI.Access_Status,
    LO.Access_LoginTimeStamp As Access_LogoutTimestamp,
    LO.Access_Status
FROM
    cte As LI
    FULL OUTER JOIN cte As LO
    ON LO.Access_Id = LI.Access_Id
    And LO.RN = LI.RN + 1
WHERE
    (LI.Access_Status = 'Login' Or LI.Access_Id Is Null)
And 
    (LO.Access_Status = 'Logout' Or LO.Access_Id Is Null)
;


Maciej Los

5ed!

chamindat

Большое вам спасибо Ричард

chamindat

вот что я сделал в конце концов

Изменить процедуру [dbo].[AUDIT_LOGINLOGOUT_MGMT]
АС

ОБЪЯВИТЬ @PREVIOUWORKINGHOUR VARCHAR(500);

НАЧАТЬ
УСТАНОВИТЕ NOCOUNT ON;

Набор @PREVIOUWORKINGHOUR = формат(функция dateadd(ДХ ,-1, getdate ()) для,'ДД/ММ/гггг чч');

ВЫБИРАТЬ
W. ACCESS_ID,
ACCESS_NAME В.,
W. ACCESS_TYPE,
W. ACCESS_USER_CC,
W. ACCESS_PROFILE_NAME,
W. ACCESS_MACHINE_NAME,
W. ACCESS_MACHINE_IP,
W. ACCESS_LOGIN_DATETIME,
W. ACCESS_LOGOUT_DATETIME
ОТ (

ВЫБИРАТЬ
Access_Id ACCESS_ID='',
ACCESS_NAME='Access_Name',
Access_Type ACCESS_TYPE ='',
Access_Country ACCESS_USER_CC='',
ACCESS_PROFILE_NAME='Access_Profile',
Access_SourceHost ACCESS_MACHINE_NAME='',
ACCESS_MACHINE_IP='Access_SourceIP',
ACCESS_LOGIN_DATETIME='Access_LoginTimeStamp',
ACCESS_LOGOUT_DATETIME='Access_LogoutTimestamp',
Rn='0'

СОЮЗ ВСЕХ

ВЫБИРАТЬ
T1.Access_Id,
Т1.Access_Name,
T1.Access_Type,
T1.Access_Country,
T1.Access_Profile,
T1.Access_SourceHost,
T1.Access_SourceIP,
T1.Access_LoginTimeStamp,
Т2.Access_LogoutTimestamp,
Ранг() над (раздел по Т1.Порядок Access_Id на Т1.Access_Id) РН
ОТ (

ВЫБИРАТЬ
ROW_NUMBER() OVER( PARTITION BY Access_Id ORDER BY Access_LoginTimeStamp) AS Row_No,
X. Access_Id,
Access_Name Х.,
X. Access_Type,
Х. Access_Country,
X. Access_Profile,
X. Access_SourceHost,
X. Access_SourceIP,
X. Access_LoginTimeStamp
ОТ
(
ВЫБИРАТЬ
T. ACCESS_ID как Access_Id,
Т. ACCESS_NAME как Access_Name,
T. ACCESS_TYPE как Access_Type,
T. ACCESS_USER_CC как Access_Country,
T. ACCESS_PROFILE_NAME как Access_Profile,
T. ACCESS_MACHINE_NAME как Access_SourceHost,
T. ACCESS_MACHINE_IP как Access_SourceIP,
T. ACCESS_DATETIME как Access_LoginTimeStamp
ОТ
(
ВЫБИРАТЬ
ACCESS_ID как Access_Id,
MAX(ACCESS_DATETIME) как Access_LoginTimeStamp
ОТ ALOGINEVENTS
Где 1=1
И (ACCESS_EVENT_STATUS=1)
И (формат(конвертировать(типа datetime,ACCESS_DATETIME,105),'ДД/ММ/гггг чч') &ЛТ; @PREVIOUWORKINGHOUR)
ГРУППА ПО ACCESS_ID
ИМЕЯ COUNT(ACCESS_ID)%2=1
) КАК М
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ALOGINEVENTS AS T ON
T. Access_Id = M. Access_Id и
T. ACCESS_DATETIME = M. Access_LoginTimeStamp
Где T. ACCESS_ID IN (
ВЫБИРАТЬ
ACCESS_ID как Access_Id
ОТ ALOGINEVENTS
Где 1=1
И (ACCESS_EVENT_STATUS=2)
И (формат(конвертировать(типа datetime,ACCESS_DATETIME,105),'ДД/ММ/гггг чч') = @PREVIOUWORKINGHOUR)
))Икс )
AS T1 LEFT JOIN (
Выберите функции row_number() над( раздел по заказу ACCESS_ID по ACCESS_DATETIME) как Row_No,
ACCESS_ID как Access_Id,
ACCESS_NAME как Access_Name,
ACCESS_TYPE как Access_Type,
ACCESS_USER_CC как Access_Country,
ACCESS_PROFILE_NAME как Access_Profile,
ACCESS_MACHINE_NAME как Access_SourceHost,
ACCESS_MACHINE_IP как Access_SourceIP,
ACCESS_DATETIME как Access_LogoutTimestamp
ОТ ALOGINEVENTS
Где 1=1
И (ACCESS_EVENT_STATUS = 2)
И (формат(конвертировать(типа datetime,ACCESS_DATETIME,105),'ДД/ММ/гггг чч') = @PREVIOUWORKINGHOUR)
) Как T2 на T1.Row_No = T2.Row_No и T1.ACCESS_ID = T2.ACCESS_ID

СОЮЗ ВСЕХ

ВЫБИРАТЬ
T1.Access_Id,
Т1.Access_Name,
T1.Access_Type,
T1.Access_Country,
T1.Access_Profile,
T1.Access_SourceHost,
T1.Access_SourceIP,
T1.Access_LoginTimeStamp,
Т2.Access_LogoutTimestamp,
Ранг() над (раздел по Т1.Порядок Access_Id на Т1.Access_Id) РН
ОТ (
Выберите функции row_number() над( раздел по заказу ACCESS_ID по ACCESS_DATETIME) как Row_No,
ACCESS_ID как Access_Id,
ACCESS_NAME как Access_Name,
ACCESS_TYPE как Access_Type,
ACCESS_USER_CC как Access_Country,
ACCESS_PROFILE_NAME как Access_Profile,
ACCESS_MACHINE_NAME как Access_SourceHost,
ACCESS_MACHINE_IP как Access_SourceIP,
ACCESS_DATETIME как Access_LoginTimeStamp
ОТ ALOGINEVENTS
Где 1=1
И (ACCESS_EVENT_STATUS = 1)
AND (FORMAT(CONVERT(DATETIME,ACCESS_DATETIME,105),'dd/