[英]How to retrieve data with group by aggregate function in SQL Server 2012
[英]SQL SERVER 2017 - How do I query to retrieve a group of data only if all of the data inside that group are marked as completed?
我有一些如下的觀察表。 觀察數據可以是由觀察類別表確定的單獨形式或成組形式。
cat table (which holds category data)
id | title | is_groupable
-------------------------------------------
1 | Cat 1 | 1
2 | Cat 2 | 1
3 | Cat 3 | 0
4 | Cat 4 | 0
5 | Cat 5 | 1
obs table (Holds observation data, groupable data are indicated by is_groupable of cat table, and the data is grouped in respect to index of obs table. and is_completed field indicates if some action has been taken on that or not)
id | cat_id | index | is_completed | created_at
------------------------------------------------------
1 | 3 | 100 | 0 | 2017-12-01
2 | 4 | 400 | 1 | 2017-12-02
// complete action taken group indicated by 1 in is_completed field
3 | 1 | 200 | 1 | 2017-12-1
4 | 1 | 200 | 1 | 2017-12-1
// not complete action taken group
5 | 2 | 300 | 0 | 2017-12-1
6 | 2 | 300 | 1 | 2017-12-1
7 | 2 | 300 | 0 | 2017-12-1
// complete action taken group
8 | 5 | 400 | 1 | 2017-12-1
9 | 5 | 400 | 1 | 2017-12-1
10 | 5 | 400 | 1 | 2017-12-1
為了便於理解,我使用obs表中的以上注釋將已完成或未使用的數據集分開。
現在,我要實現的是從obs表中以組格式檢索數據集。 在上述情況下,組的集合是
{3,4}
{5,6,7}
{8,9,10}
我想在結果中設置{3,4}和{8,9,10},因為該組中的每個數據都標記為is_completed:1我不需要{5,6,7}數據集,因為它只有6個標記為已完成,5個和7個未采取行動,因此未完成。
到目前為止,我所做的是(讓我們忽略單個案例,因為它非常簡單並且已經完成,對於分組案例,如果忽略所采取的措施,我也可以檢索分組數據,即我可以分組它們並檢索集合,無論是否采取了行動。)
(SELECT
null AS id,
cat.is_groupable AS is_grouped,
cat.title,
cat.id AS category_id,
o.index,
o.date,
null AS created_at,
null AS is_action_taken,
(
-- individual observation
SELECT
oi.id AS "observation.id",
oi.category_id AS "observation.category_id",
oi.index AS "observation.index",
oi.created_at AS "observation.created_at",
-- action taken flag according to is_completed
CAST(
CASE
WHEN ((oi.is_completed) > 0) THEN 1
ELSE 0
END AS BIT
) AS "observation.is_action_taken",
-- we might do some sort of comparison here
CAST(
(
CASE
--
-- Check if total count == completed count
WHEN (
SELECT COUNT(obs.id)
FROM obs
WHERE obs.category_id = cat.id AND obs.index = o.index
) = (
SELECT COUNT(obs.id)
FROM obs
WHERE obs.category_id = cat.id AND oi.index = o.index
AND oi.is_action_taken = 1
) then 1
else 0
end
) as bit
) as all_completed_in_group
FROM observations oi
WHERE oi.category_id = cat.id
AND oi.index = o.index
FOR JSON PATH
) AS observations
FROM obs o
INNER JOIN cat ON cat.id = o.category_id
WHERE cat.is_groupable = 1
GROUP BY cat.id, cat.name, o.index, cat.is_groupable, o.created_at
)
讓我們不要繼續該查詢是否成功執行。 我只是想知道,是否有比該方法更好的方法,或者該方法是否正確。
希望這是您所需要的。 為了檢查組的完整性,我剛剛對具有is_completed = '0'
的組使用了AND NOT EXISTS
。 內部聯接用於獲取相應的obs id。 該算法放在CTE(公用表表達式)中。 然后,我在CTE上使用STUFF來獲取輸出。
DECLARE @cat TABLE (id int, title varchar(100), is_groupable bit)
INSERT INTO @cat VALUES
(1, 'Cat 1', 1), (2, 'Cat 2', 1), (3, 'Cat 3', 0), (4, 'Cat 4', 0), (5, 'Cat 5', 1)
DECLARE @obs TABLE (id int, cat_id int, [index] int, is_completed bit, created_at date)
INSERT INTO @obs VALUES
(1, 3, 100, 0, '2017-12-01'), (2, 4, 400, 1, '2017-12-02')
-- complete action taken group indicated by 1 in is_completed field
,(3, 1, 200, 1, '2017-12-01'), (4, 1, 200, 1, '2017-12-01')
-- not complete action taken group
,(5, 2, 300, 0, '2017-12-01'), (6, 2, 300, 1, '2017-12-01'), (7, 2, 300, 0, '2017-12-01')
-- complete action taken group
,(8, 5, 400, 1, '2017-12-01'), (9, 5, 400, 1, '2017-12-01'), (10, 5, 400, 1, '2017-12-01')
;
WITH cte AS
(
SELECT C.id [cat_id]
,O2.id [obs_id]
FROM @cat C INNER JOIN @obs O2 ON C.id = O2.cat_id
WHERE C.is_groupable = 1 --is a group
AND NOT EXISTS (SELECT *
FROM @obs O
WHERE O.cat_id = C.id
AND O.is_completed = '0'
--everything in the group is_completed
)
)
--Stuff will put everything on one row
SELECT DISTINCT
'{'
+ STUFF((SELECT ',' + CAST(C2.obs_id as varchar)
FROM cte C2
WHERE C2.cat_id = C1.cat_id
FOR XML PATH('')),1,1,'')
+ '}' AS returnvals
FROM cte C1
產生輸出:
returnvals
{3,4}
{8,9,10}
我會嘗試這種方法,訣竅是使用已完成的總和來對照該組的總存在量進行檢查。
;WITH aux AS (
SELECT o.cat_id, COUNT(o.id) Tot, SUM(CONVERT(int, o.is_completed)) Compl, MIN(CONVERT(int, c.is_groupable)) is_groupable
FROM obs o INNER JOIN cat c ON o.cat_id = c.id
GROUP BY o.cat_id
)
, res AS (
SELECT o.*, a.is_groupable
FROM obs o INNER JOIN aux a ON o.cat_id = a.cat_id
WHERE (a.Tot = a.Compl AND a.is_groupable = 1) OR a.Tot = 1
)
SELECT CONVERT(nvarchar(10), id) id, CONVERT(nvarchar(10), cat_id) cat_id
INTO #res
FROM res
SELECT * FROM #res
SELECT m.cat_id, LEFT(m.results,Len(m.results)-1) AS DataGroup
FROM
(
SELECT DISTINCT r2.cat_id,
(
SELECT r1.id + ',' AS [text()]
FROM #res r1
WHERE r1.cat_id = r2.cat_id
ORDER BY r1.cat_id
FOR XML PATH ('')
) results
FROM #res r2
) m
ORDER BY DataGroup
DROP TABLE #res
轉換歸因於位數據類型
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.