Выберите всех людей, которые имеют определенные свойства на данную дату - PullRequest
0 голосов
/ 03 июня 2019

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

ID  StartDate   ValueString ValueFloat  ValueDate   Individus_ID    IndividusDynProp
14  2018-09-10  Outside     NULL        NULL        3               Out Status
13  2018-08-15  Dead        NULL        NULL        1               Out Status
12  2018-08-02  Male        NULL        NULL        3               Sex
11  2018-07-28  #DBNULL#    NULL        NULL        1               Out Status
10  2018-07-25  Sold        NULL        NULL        1               Out Status
9   2018-06-07  Unk         NULL        NULL        3               Sex
8   2018-06-07  Adult       NULL        NULL        3               Status
7   2018-06-06  Femal       NULL        NULL        2               Sex
6   2018-06-06  Adult       NULL        NULL        2               Status
5   2018-06-03  Male        NULL        NULL        1               Sex
4   2018-06-03  Adult       NULL        NULL        1               Status
3   2018-05-23  Egg         NULL        NULL        3               Status
2   2018-05-23  Egg         NULL        NULL        2               Status
1   2018-05-21  Egg         NULL        NULL        1               Status

'# DBNULL #' означает, что данное лицо снова находится на сайте.Я хочу создать функцию, которая берет дату для входного параметра и возвращает таблицу с идентификатором каждого человека, принадлежащего к группе «Мужчина, живущий на месте» на дату.Человек входит в группу, если пол = «мужской» И (состояние «Out» равно NULL или «Out» = «# DBNULL #»). Так, в примере, если в функцию введена дата «2018-07-20»,возвращает:

Individus_ID
1

, если дата «2018-08-10», возвращается:

 Individus_ID
 3
 1

, если дата «2018-08-17», возвращается:

Individus_ID
3

Я пробовал это:

CREATE FUNCTION fn_Groupe_Individus_Male_Vivant (@daDate datetime)
RETURNS @TGrMalesVivants TABLE (
        TList_Individual [varchar] (50) NOT NULL 
    )

AS

BEGIN

DECLARE @TtempGrMalesVivants TABLE (TList_Individual [varchar] (50) NOT NULL)    
DECLARE @TtempGrMales TABLE (TList_MIndividual int NOT NULL)

INSERT INTO @TtempGrMales 
    SELECT DISTINCT Individus_ID
    FROM IndividusDynPropValues

DECLARE @selectedOutStatus VARCHAR(50),
        @sBirdId int,
        @tmpSex VARCHAR(3)

WHILE EXISTS (SELECT * FROM @TtempGrMales)
                BEGIN

                    SELECT TOP 1 @sBirdId = TList_MIndividual FROM @TtempGrMales 

                    SELECT @selectedOutStatus =IDPV.ValueString
                                        FROM [dbo].[IndividusDynPropValues] AS IDPV
                                        WHERE NOT EXISTS (SELECT *
                                                    FROM [dbo].[IndividusDynPropValues] AS IDPV2
                                                    WHERE IDPV.Individus_ID=IDPV2.Individus_ID
                                                    AND IDPV.IndividusDynProp_ID=IDPV2.IndividusDynProp_ID
                                                    AND IDPV2.StartDate>IDPV.StartDate AND CONVERT(smalldatetime,IDPV2.StartDate,120 )<=@daDate)
                                        AND CONVERT(smalldatetime,IDPV.StartDate,120 )<=@daDate
                                        AND IDPV.Individus_ID =@sBirdId
                                        AND IDPV.IndividusDynProp_ID='Out Status'


                    SELECT @tmpSex= IDPV.ValueString
                    FROM [dbo].[IndividusDynPropValues] AS IDPV
                    INNER JOIN TSaisie AS TS ON TS.TSai_PK_ID=IDPV.Saisie_ID
                    INNER JOIN TProtocole AS TP ON TP.TPro_PK_ID=TS.TSai_FK_TPro_ID
                    WHERE NOT EXISTS (SELECT *
                                FROM [dbo].[IndividusDynPropValues] AS IDPV2
                                WHERE IDPV.Individus_ID=IDPV2.Individus_ID
                                AND IDPV.IndividusDynProp_ID=IDPV2.IndividusDynProp_ID
                                AND IDPV2.StartDate>IDPV.StartDate AND CONVERT(smalldatetime,IDPV2.StartDate,120 )<=@daDate)
                    AND CONVERT(smalldatetime,IDPV.StartDate,120 )<=@daDate
                    AND IDPV.Individus_ID =@sBirdId
                    AND IDPV.IndividusDynProp_ID='Sex'
                    AND TPro_Importance = (SELECT Max(TP2.Tpro_Importance) 
                                              FROM IndividusDynPropValues IDPV3
                                              INNER JOIN TSaisie AS TS2 ON TS2.TSai_PK_ID=IDPV3.Saisie_ID
                                              INNER JOIN TProtocole AS TP2 ON TP2.TPro_PK_ID=TS2.TSai_FK_TPro_ID
                                                WHERE IDPV3.Individus_ID=@sBirdId
                                                AND IDPV3.IndividusDynProp_ID=4
                                                AND IDPV3.StartDate>=IDPV.StartDate
                                                AND CONVERT(smalldatetime,IDPV3.StartDate,120 )<=@daDate)

                    IF @tmpSex='Male' AND (@selectedOutStatus IS NULL OR @selectedOutStatus='#DBNULL#')
                        BEGIN 

                            INSERT INTO @TtempGrMalesVivants (TList_Individual) 
                            VALUES (@sBirdId)

                        END

                    DELETE TOP (1) FROM @TtempGrMales
                END

 INSERT @TGrMalesVivants
    SELECT * 
    FROM @TtempGrMalesVivants
    RETURN 

 END

это работает, но занимает 1:55 со всей таблицей (1859732 строки), поэтому это слишком долго

1 Ответ

0 голосов
/ 06 июня 2019

Мне кажется, я понимаю, что вы пытаетесь сделать. Обратите внимание, как я разместил пример данных? Это хороший пример того, что вы должны делать в будущем.

Здесь должно работать некоторое условное агрегирование. Вам нужна эта агрегация, потому что ваши данные денормализованы в EAV, и вам нужно собрать их в нормализованную таблицу. Это работает для данных образца и желаемого результата. Вы можете раскомментировать строку set @MyDate, чтобы увидеть, как работает второе значение.

if OBJECT_ID('tempdb..#IndividusDynPropValues') is not null
    drop table #IndividusDynPropValues

create table #IndividusDynPropValues
(
    ID int
    , StartDate date
    , ValueString varchar(50)
    , ValueFloat float
    , ValueDate date
    , Individus_ID int
    , IndividusDynProp varchar(50)
)

insert #IndividusDynPropValues values
(14, '2018-09-10', 'Outside', NULL, NULL, 3, 'Out Status')
, (13, '2018-08-15', 'Dead', NULL, NULL, 1, 'Out Status')
, (12, '2018-08-02', 'Male', NULL, NULL, 3, 'Sex')
, (11, '2018-07-28', '#DBNULL#', NULL, NULL, 1, 'Out Status')
, (10, '2018-07-25', 'Sold', NULL, NULL, 1, 'Out Status')
, (9 , '2018-06-07', 'Unk' , NULL, NULL, 3, 'Sex')
, (8 , '2018-06-07', 'Adult' , NULL, NULL, 3, 'Status')
, (7 , '2018-06-06', 'Femal' , NULL, NULL, 2, 'Sex')
, (6 , '2018-06-06', 'Adult' , NULL, NULL, 2, 'Status')
, (5 , '2018-06-03', 'Male' , NULL, NULL, 1, 'Sex')
, (4 , '2018-06-03', 'Adult' , NULL, NULL, 1, 'Status')
, (3 , '2018-05-23', 'Egg' , NULL, NULL, 3, 'Status')
, (2 , '2018-05-23', 'Egg' , NULL, NULL, 2, 'Status')
, (1 , '2018-05-21', 'Egg' , NULL, NULL, 1, 'Status')

declare @MyDate date = '20180720' --returns Individus_ID 1
--set @MyDate = '20180810' --returns Individus_ID 1, 3
;

with MySortedData as
(
    select i.*
        , RowNum = ROW_NUMBER()over(partition by i.Individus_ID, i.IndividusDynProp order by i.StartDate desc)
    from #IndividusDynPropValues i
    where i.StartDate <= @MyDate
)

select s.Individus_ID
    , OutStatus = max(case when IndividusDynProp = 'Out Status' then ValueString end)
    , Status = max(case when IndividusDynProp = 'Status' then ValueString end)
    , Sex = max(case when IndividusDynProp = 'Sex' then ValueString end)
from MySortedData s
where s.RowNum = 1      
group by s.Individus_ID
having isnull(max(case when IndividusDynProp = 'Out Status' then ValueString end), '#DBNULL#') = '#DBNULL#'
    and max(case when IndividusDynProp = 'Sex' then ValueString end) = 'Male'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...