Boy Balantoy Ответов: 1

Как получить количество элементов по категориям из связанных таблиц MSSQL 2000?


Всем привет. В настоящее время я разрабатываю простую систему инвентаризации и немного новичок в TSQL. И вот моя проблема: мне нужна некоторая помощь в надежде, что вы сможете оказать мне некоторую помощь. У меня есть три таблицы с именами HDR, DTL и MODEL. Они содержат примеры данных, как показано ниже :
HDR TABLE			
    DOCID	DOCNO	DOCTYPE	APPTYPE
    0001	ABCDD	C	1000
    0002	ABCDE	C	1000
    0003	ABCDF	D	1001

DTL TABLE			
    DTLID	DOCID	MODELID	ENGINE NO.
    1	0001	1001	1111
    2	0001	1001	1112
    3	0002	1002	1113
    4	0002	1002	1114
    5	0003	1002	1114

MODEL TABLE
    MODELID	MODEL
    1001	MODEL1
    1002	MODEL2

Теперь мне нужно сгенерировать отчет, выглядящий следующим образом:
REPORT				
    MODELNAME	INITIAL	ENTRY	TRANSFER	BALANCE
    MODEL1	2	2	0	2
    MODEL2	2	2	1	1


Для дальнейшего изложения мне нужно показать начальный отсчет конкретной модели в инвентаре. Затем подсчитайте, сколько раз модель была "вставлена "в базу данных, обозначенную как" запись " связанным с ней HDR DOCTYPE = 'D' (Дебет). Кроме того, мне также нужно подсчитать, сколько раз конкретная модель была отмечена как "out" в базе данных, обозначенной как "TRANSFER" соответствующим ДОКТИПОМ HDR как "D". И, основываясь на этих типах записей, подсчитайте оставшийся остаток (начальный перевод) в базе данных. Я пробовал различные подходы и, похоже, мне сошел с рук сценарий, который почему-то выглядит так:

use mss
declare @dtb as datetime
declare @dte as datetime
select @dtb = '2016-01-01'
select @dte = '2017-03-01'

select m.modelid, m.model, 
--begin
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and d.apptype in (1,3) or (d.apptype = 7 and hdr.doctype like 'D')
and hdr.rcvdt between @dtb and @dte 
) as Beginning,

--sales
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and d.apptype = 2
and hdr.docdt between @dtb and @dte 
) as Sales,

--delivery
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and hdr.apptype = 1
and hdr.rcvdt between @dtb and @dte 
) as Delivery,

--MT
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and hdr.apptype = 5
and hdr.rcvdt between @dtb and @dte 
) as Transfer,

--service unit
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and hdr.apptype = 6
and hdr.docdt between @dtb and @dte 
) as [Service Unit],

--repossesed
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and hdr.apptype = 3
and hdr.docdt between @dtb and @dte 
) as Delivery,

--adj
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and hdr.apptype = 7 and hdr.doctype = 'D'
and hdr.rcvdt between @dtb and @dte 
) as [ADJ-DB],

--adj
(
select count(*) from invdtl d 
join invhdr hdr on d.docid = hdr.docid
where d.modelid = m.modelid and hdr.apptype = 7 and hdr.doctype = 'C'
and hdr.rcvdt between @dtb and @dte 
) as [ADJ-CR]


from model m

--join
where 
m.modelid in (select distinct d.modelid from invdtl d) 
order by m.model asc

select * from invdtl where modelid = 519


что дает желаемый результат на фиктивной базе данных, которую я создал со скудными 200 записями. Но когда я попробовал его на своей реальной тестовой базе данных с более чем 100 тысячами записей, загрузка данных заняла целую вечность. Какие-нибудь советы о том, как добиться того же результата без необходимости так долго ждать результата сценария, который я пробовал? Ваша помощь будет очень признательна :)

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

попробовал что-то вроде такого подхода :

ВЫБИРАТЬ
категория,
COUNT (*) AS 'num'
ОТ
сообщений
ГРУППА ПО
категория

но мне было трудно изменить свой сценарий в соответствии с тем же подходом.

1 Ответов

Рейтинг:
12

Richard Deeming

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

USE mss;

DECLARE @dtb as datetime = '20160101';
DECLARE @dte as datetime = '20170301';

WITH cteStats As
(
    SELECT
        d.modelid,
        SUM(CASE
            WHEN hdr.apptype In (1, 3) THEN 1
            WHEN hdr.apptype = 7 And hdr.doctype like 'D' THEN 1
            ELSE 0
        END) As Beginning,
        SUM(CASE
            WHEN hdr.apptype = 2 THEN 1
            ELSE 0
        END) As Sales,
        SUM(CASE
            WHEN hdr.apptype = 1 THEN 1
            ELSE 0
        END) As Delivery,
        SUM(CASE
            WHEN hdr.apptype = 5 THEN 1
            ELSE 0
        END) As Transfer,
        SUM(CASE
            WHEN hdr.apptype = 6 THEN 1
            ELSE 0
        END) As [Service Unit],
        SUM(CASE
            WHEN hdr.apptype = 3 THEN 1
            ELSE 0
        END) As Repossessed,
        SUM(CASE
            WHEN hdr.apptype = 7 and hdr.doctype = 'D' THEN 1
            ELSE 0
        END) As [ADJ-DB],
        SUM(CASE
            WHEN hdr.apptype = 7 and hdr.doctype = 'C' THEN 1
            ELSE 0
        END) As [ADJ-CR]
    FROM
        dbo.invdtl As d
        INNER JOIN dbo.invhdr As hdr
        ON hdr.docid = d.docid
    WHERE
        hdr.rcvdr BETWEEN @dtb And @dte
    GROUP BY
        d.modelid
)
SELECT
    m.modelid,
    m.model,
    s.Beginning,
    s.Sales,
    s.Delivery,
    s.Transfer,
    s.[Service Unit],
    s.Repossessed,
    s.[ADJ-DB],
    s.[ADJ-CR]
FROM
    dbo.model As m
    INNER JOIN cteStats As s
    ON s.modelid = m.modelid
ORDER BY
    m.model ASC
;


Boy Balantoy

Господи, это именно то, что я искал. большое спасибо, сэр Ричард! Конечно, это облегчает задачу, если вы стараетесь держать свой ум открытым для идей других людей о том, как подойти к вашей проблеме. Большое спасибо также за то, что вы проанализировали мой сценарий и привели пример, основанный именно на именах таблиц и столбцов, которые я использовал, что сделало его более удобным для меня, чтобы просто протестировать его сразу, а не тратить время на изменение вашего данного сценария. Снова и снова, миллион благодарностей! :)