Выбрать все даты, между которыми объект обладает определенными свойствами - PullRequest
3 голосов
/ 16 мая 2019

Я использую динамические свойства для управления характеристиками отдельных лиц. У меня есть таблица IndividualidDynPropValues ​​с 1 строкой для каждого человека и каждого свойства Например:

ID  IndividualID    ValueString  ValueFloat      ValueDate StartDate   Prop
108 2               Outside      NULL            NULL      2018-06-17  Out Status
107 2               Male         NULL            NULL      2018-05-17  Sex
106 1               Dead         NULL            NULL      2018-08-17  Out Status
105 2               Unk          NULL            NULL      2018-04-03  Sex
104 2               Adult        NULL            NULL      2018-04-03  Status
103 1               Femal        NULL            NULL      2018-03-27  Sex
102 1               Adult        NULL            NULL      2018-03-27  Status
101 2               Egg          NULL            NULL      2018-03-25  Status
100 1               Egg          NULL            NULL      2018-03-17  Status

Я хочу просмотреть таблицу со всеми живущими мужчинами (например, пол = «мужчина» и «нет» = «взрослый» и «нет» <> «мертв») между двумя датами, используя только один SELECT. Поэтому в примере я хочу выбрать:

IndividualID    BeginDate          End Date      Group
2               2018-05-17         2019-05-16    Living male individuals

Это возможно? Как это сделать?

Я пробовал это для группы «Все взрослые»:

SELECT IDPV1.[IndividualID]
      ,IDPV1.[StartDate] AS BeginDate
     ,GETDATE() AS EndDate
     ,IDPV1.[ValueString]
     ,'All Adult' AS [Group]
   FROM [dbo].[IndividusDynPropValues] IDPV1
   WHERE IDPV1.ValueString='Adulte'

Но он не работал с несколькими свойствами ...

Ответы [ 3 ]

2 голосов
/ 16 мая 2019

Другой возможный подход заключается в подсчете совпадений и использовании соответствующего предложения HAVING:

Таблица:

CREATE TABLE #IDVP1 (
    ID int,
    IndividualID int,
    ValueString varchar(50),
    StartDate date,   
    Prop varchar(50)
)
INSERT INTO #IDVP1 
    (ID, IndividualID, ValueString, StartDate, Prop)
VALUES
    (108, 2, 'Outside', '20180617', 'Out Status'),
    (107, 2, 'Male',    '20180517', 'Sex'),
    (106, 1, 'Dead',    '20180817', 'Out Status'),
    (105, 2, 'Unk',     '20180403', 'Sex'),
    (104, 2, 'Adult',   '20180403', 'Status'),
    (103, 1, 'Femal',   '20180327', 'Sex'),
    (102, 1, 'Adult',   '20180327', 'Status'),
    (101, 2, 'Egg',     '20180325', 'Status'),
    (100, 1, 'Egg',     '20180317', 'Status')

Заявление:

SELECT 
    IndividualID, 
    MIN(CASE WHEN (Prop = 'Sex') AND (ValueString = 'Male') THEN StartDate END) AS BeginDate,
    MIN(CASE WHEN (Prop = 'Out Status') AND (ValueString = 'Dead') THEN StartDate ELSE GETDATE() END) AS EndDate,
    'Living male individuals' AS [Group]
FROM #IDVP1
GROUP BY IndividualID
HAVING 
    SUM(
        CASE WHEN (Prop = 'Sex') AND (ValueString = 'Male') THEN 1 ELSE 0 END +
        CASE WHEN (Prop = 'Status') AND (ValueString = 'Adult') THEN 1 ELSE 0 END +
        CASE WHEN (Prop = 'Out Status') AND (ValueString <> 'Dead') THEN 1 ELSE 0 END
    ) = 3

Вывод (на основе данных вашего примера соответствует только одна строка):

IndividualID    BeginDate           EndDate             Group
2               17/05/2018 00:00:00 17/05/2019 11:39:42 Living male individuals
1 голос
/ 16 мая 2019

Использование CTE:

Create Table #tbl
(
ID Int,
IndividualID Int,
ValueString VarChar(10),
ValueFloat Float,
ValueDate Date,
StartDate Date,
Prop VarChar(15)
)
Insert Into #tbl Values
(108,2,'Outside',NULL,NULL,'2018-06-17','Out Status'),
(107,2,'Male',NULL,NULL,'2018-05-17','Sex'),
(106,1,'Dead',NULL,NULL,'2018-08-17','Out Status'),
(105,2,'Unk',NULL,NULL,'2018-04-03','Sex'),
(104,2,'Adult',NULL,NULL,'2018-04-03','Status'),
(103,1,'Femal',NULL,NULL,'2018-03-27','Sex'),
(102,1,'Adult',NULL,NULL,'2018-03-27','Status'),
(101,2,'Egg',NULL,NULL,'2018-03-25','Status'),
(100,1,'Egg',NULL,NULL,'2018-03-17','Status')

CTE:

;With cte As
(
Select IndividualID,
      Max(Case When Prop = 'Out Status' And ValueString = 'Dead' Then 'Y' Else 'N' End) As Dead,
      Max(Case When Prop = 'Status' And ValueString <> 'Adult' Then 'Y' Else 'N' End) As Adult,
      Max(Case When Prop = 'Sex' And ValueString = 'Male' Then 'Y' Else 'N' End) As Male,
      Min(StartDate) As StartDT,
      Max(StartDate) As EndDT,
      'Living male individuals' As [Group]
From #tbl
Group By IndividualID
)
Select * From cte Where Male = 'Y' And Adult = 'Y' And Dead = 'N'
0 голосов
/ 16 мая 2019

Попробуйте использовать агрегат, чтобы получить список идентификаторов.

Create Table #tbl
(
ID Int,
IndividualID Int,
ValueString VarChar(10),
ValueFloat Float,
ValueDate Date,
StartDate Date,
Prop VarChar(15)
)
Insert Into #tbl Values
(108,2,'Outside',NULL,NULL,'2018-06-17','Out Status'),
(107,2,'Male',NULL,NULL,'2018-05-17','Sex'),
(106,1,'Dead',NULL,NULL,'2018-08-17','Out Status'),
(105,2,'Unk',NULL,NULL,'2018-04-03','Sex'),
(104,2,'Adult',NULL,NULL,'2018-04-03','Status'),
(103,1,'Femal',NULL,NULL,'2018-03-27','Sex'),
(102,1,'Adult',NULL,NULL,'2018-03-27','Status'),
(101,2,'Egg',NULL,NULL,'2018-03-25','Status'),
(100,1,'Egg',NULL,NULL,'2018-03-17','Status')


Select IDPV1.IndividualID
    , MIN(STartDate) as BeginDate
    , MAX(StartDate) as EndDate
    , 'Living male individuals' as [group]
from #tbl IDPV1
where (Prop='Sex' and ValueString='Male')
    or (Prop='Status' and valuestring='Adult')
    and not exists(select 1 
                   from #tbl sub
                   where sub.IndividualID=IDPV1.IndividualID
                      and sub.Prop = 'Out Status' and sub.Prop='Dead')

group by IndividualID
having count(*)=2

Результаты:

IndividualID    BeginDate   EndDate     group
2               2018-04-03  2018-05-17  Living male individuals
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...