2016-09-16 395 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