2016-09-16 91 views
0

數據組中的遺漏值最近我需要基於事實的報告:查找使用SQL

TableA的有以下兩列的用戶ID和DocumentType

我已經提供的「強制性名單'文檔類型:Type1,Type2,Type3和我需要返回沒有全部三種類型的每個用戶ID以及缺少的類型。

例如,如果表A中包含以下行

12 Type1 
12 Type2 
12 Type4 
13 Type1 
13 Type2 
13 Type3 
14 Type1 
15 Type6 
15 Type7 
15 Type8 

那麼理想的輸出會是這樣的:

12 Type3 
14 Type2, Type3 
15 Type1, Type2, Type3 

理想的情況下,產生的結果的查詢應該能夠處理高達數千萬條記錄。

我們最近使用SQL Server 2012實現了類似問題的解決方案(這比這更復雜一點)。需要3分半鐘的時間才能在多個表中獲得完整報告,總計約有400萬條記錄。我們想知道是否有更好的想法可以更快地做到這一點。

請隨時分享您的想法,可以解決這個問題。

謝謝! :)

+1

'然後從表A組*具有ID COUNT(*)<3' –

+0

謝謝你的評論,馬克。用戶可能有3種不需要的類型。我會更新我的問題,使其更加精確。 ;) –

+1

你標記了mysql和sql-server,但是你提到你用sql-server 2012做了這個,但是這是哪個呢?你是否在mysql或sql-server這樣做了這個行來連接字符串是非常不一樣的! – Matt

回答

0

最簡單的辦法

SELECT DISTINCT UserID 
FROM your_table 

EXCEPT 

(
    SELECT UserID 
    FROM your_table 
    WHERE DocumentType = ('Type1') 

    UNION 

    SELECT UserID 
    FROM your_table 
    WHERE DocumentType = ('Type2') 

    UNION 

    SELECT UserID 
    FROM your_table 
    WHERE DocumentType = ('Type3') 
) 

不能更準確的比這個規則 - 讓你的編譯器將着眼於指標等,並進行優化。

除非有部分問題沒有告訴我們。

0

我認爲你需要像這樣

select x2.* 
(select * 
from (select distinct UserID from [table])x 
cross join 
(select 'type1' DocumentType union 
select 'type2' union 
select 'type3') y 
) x2 
left join [table] y2 
on y2.UserID = x2.UserID 
and y2.DocumentType = x2.DocumentType 
where y2.DocumentType is null 
order by x2.UserID 
0

DEMO

WITH 
base ([DocumentType]) as (
    SELECT 'Type1' UNION ALL 
    SELECT 'Type2' UNION ALL 
    SELECT 'Type3' 
), 
users as (
    SELECT DISTINCT [userID] 
    FROM Table1 t  
), 
pairs as ( 
    SELECT * 
    FROM users, base 
)  
SELECT p.userID, p.[DocumentType], t.[DocumentType] 
FROM pairs p 
LEFT JOIN Table1 t 
     ON p.[DocumentType] = t.[DocumentType] 
     AND p.[userID] = t.[userID] 
WHERE t.[DocumentType] IS NULL 

輸出

enter image description here

1

這裏是FOR XML路徑的級聯方法:

CREATE TABLE TableA (ID INT, TypeCol CHAR(5)); 
INSERT INTO TableA (ID,TypeCol) VALUES (12,'Type1') 
,(12,'Type2') 
,(12,'Type4') 
,(13,'Type1') 
,(13,'Type2') 
,(13,'Type3') 
,(14,'Type1') 
,(15,'Type6') 
,(15,'Type7') 
,(15,'Type8') 

;WITH cteRequiredTypes AS (
    SELECT 'type1' as TypeCol 
    UNION ALL 
    SELECT 'type2' 
    UNION ALL 
    SELECT 'type3' 
) 

, cteTableAIds AS (
    SELECT DISTINCT Id 
    FROM 
     TableA 
) 

, cteMissingTypes AS (
    SELECT 
     i.ID 
     ,r.TypeCol 
    FROm 
     cteRequiredTypes r 
     CROSS JOIN cteTableAIds i 
     LEFT JOIN TableA a 
     ON r.TypeCol = a.TypeCol 
     AND i.ID = a.ID 
    WHERE 
     a.ID IS NULL 
) 


SELECT 
    DISTINCT a.ID 
    ,STUFF(
     (SELECT ',' + TypeCol 
     FROM 
      cteMissingTypes t 
     WHERE t.ID = a.ID 
     FOR XML PATH('')) 

     ,1,1,'') 
FROM 
    cteMissingTypes a 

相信對於檢查大型數據集有條件的聚集查詢將可能是更好的性能。

條件聚合

SELECT 
    ID 
    ,CASE WHEN SUM(IIF(TypeCol = 'type1',1,0)) = 0 THEN 'type1' ELSE '' END as Type1 
    ,CASE WHEN SUM(IIF(TypeCol = 'type2',1,0)) = 0 THEN 'type2' ELSE '' END as Type2 
    ,CASE WHEN SUM(IIF(TypeCol = 'type3',1,0)) = 0 THEN 'type3' ELSE '' END as Type3 
    ,STUFF(
     REPLACE (
     REPLACE (
     + ',' + CASE WHEN SUM(IIF(TypeCol = 'type1',1,0)) = 0 THEN 'type1' ELSE '' END 
     + ',' + CASE WHEN SUM(IIF(TypeCol = 'type2',1,0)) = 0 THEN 'type2' ELSE '' END 
     + ',' + CASE WHEN SUM(IIF(TypeCol = 'type3',1,0)) = 0 THEN 'type3' ELSE '' END 
     ,',,,',',,') 
     ,',,',',') 
     ,1,1,'') as MissingTypeList 
FROM 
    TableA 
GROUP BY 
    ID 
HAVING 
    SUM(IIF(TypeCol = 'type1',1,0)) = 0 
    OR SUM(IIF(TypeCol = 'type2',1,0)) = 0 
    OR SUM(IIF(TypeCol = 'type3',1,0)) = 0