通过查看单个列的多个值来过滤结果

时间:2018-09-05 18:19:04

标签: sql

我有一个表,该表具有按帐户关联的每个设备的数据:

account_id  |  model
1           |   iPhone
1           |   Samsung 
2           |   iPhone
3           |   Samsung
4           |   iPhone
4           |   Samsung
4           |   LG

我正在尝试创建一个查询,在其中我收集属于以下存储桶之一的帐户ID:仅iPhone ,三星 或iPhone和Samsung 。

在此示例中,他们希望帐户ID#4落入iPhone和Samsung的存储桶中。

到目前为止,我的结果产生了重叠,这将导致查询问题。

任何有关如何构造查询以产生这些结果的帮助都会有所帮助

谢谢你,   丹妮尔

3 个答案:

答案 0 :(得分:0)

使用条件聚合

select account_id  
from tables
group by account_id  
having count(distinct model)=1

示例 http://sqlfiddle.com/#!9/146a533/1

答案 1 :(得分:0)

此解决方案假定您的DBMS支持窗口功能。如果不是这种情况,请标记您的DBMS。会更加复杂。

SELECT TD1.*,
       CASE WHEN MAX(CASE WHEN model = 'Samsung' THEN 1 ELSE 0 END) OVER
                   ( PARTITION BY account_id) = 1
             AND MAX(CASE WHEN model <> 'Samsung' THEN 1 ELSE 0 END) OVER
                   ( PARTITION BY account_id) = 0 THEN 'Samsung Only'
            WHEN MAX(CASE WHEN model = 'iPhone' THEN 1 ELSE 0 END) OVER
                   ( PARTITION BY account_id) = 1
             AND MAX(CASE WHEN model <> 'iPhone' THEN 1 ELSE 0 END) OVER
                   ( PARTITION BY account_id) = 0 THEN 'iPhone Only'
            WHEN MAX(CASE WHEN model = 'iPhone' THEN 1 ELSE 0 END) OVER
                   ( PARTITION BY account_id) = 1
             AND MAX(CASE WHEN model = 'Samsung' THEN 1 ELSE 0 END) OVER
                   ( PARTITION BY account_id) = 1 THEN 'iPhone and Samsung'
            ELSE 'Other'                   
        END AS Product_Tag
  FROM TEST_DATA;

编辑:如果您的DBMS支持CTE,那也不错...

WITH TAGGED 
  ( SELECT Account_ID,
           SUM(CASE WHEN model = 'Samsung' THEN 1 ELSE 0 END) AS Samsung_Count,
           SUM(CASE WHEN model = 'iPhone' THEN 1 ELSE 0 END) AS iPhone_Count,
           SUM(CASE WHEN model NOT IN ('iPhone','Samsung') THEN 1 ELSE 0 END) AS Neither_Count
      FROM (SELECT DISTINCT Account_ID,
                            model
              FROM TEST_DATA
           ) TMP
     GROUP
        BY Account_ID
  )
SELECT TD1.*,
       'Samsung Only'
  FROM TEST_DATA TD1
 WHERE EXISTS 
         ( SELECT 1
             FROM Tagged
            WHERE Samsung_Count = 1
              AND iPhone_Count = 0
              AND Neither_Count = 0
              AND Tagged.account_id = TD1.account_id
         )
 UNION
SELECT TD1.*,
       'iPhone Only'
  FROM TEST_DATA TD1
 WHERE EXISTS 
         ( SELECT 1
             FROM Tagged
            WHERE Samsung_Count = 0
              AND iPhone_Count = 1
              AND Neither_Count = 0
              AND Tagged.account_id = TD1.account_id
         ) 
 UNION
SELECT TD1.*,
       'iPhone and Samsung Only'
  FROM TEST_DATA TD1
 WHERE EXISTS 
         ( SELECT 1
             FROM Tagged
            WHERE Samsung_Count = 1
              AND iPhone_Count = 1
              AND Neither_Count = 0
              AND Tagged.account_id = TD1.account_id
         );

如果它都不支持...那不漂亮

SELECT TD1.*,
       'Samsung Only'
  FROM TEST_DATA TD1
 WHERE TD1.model = 'Samsung'
   AND NOT EXISTS
         ( SELECT 1
             FROM TEST_DATA TD2
            WHERE TD1.model <> TD2.model
         )
 UNION        
SELECT TD1.*,
       'iPhone Only'
  FROM TEST_DATA TD1
 WHERE TD1.model = 'iPhone'
   AND NOT EXISTS
         ( SELECT 1
             FROM TEST_DATA TD2
            WHERE TD1.model <> TD2.model
         )
 UNION    
SELECT TD1.*,
       'Samsung and iPhone'
  FROM TEST_DATA TD1
 WHERE EXISTS 
         ( SELECT 1
             FROM (SELECT account_id,
                          SUM
                            ( CASE WHEN model = 'iPhone' THEN 1
                                   WHEN model = 'Samsung' THEN 1
                                   ELSE 0
                               END
                            ) AS product_agg
                     FROM (SELECT DISTINCT
                                  account_id,
                                  model
                             FROM TEST_DATA
                          ) TMP
                  ) TMP2
            WHERE TMP2.product_agg = 2
              AND TD1.account_id = TMP2.account_id
         )
   AND NOT EXISTS
         ( SELECT 1
             FROM TEST_DATA TD2
            WHERE TD2.model NOT IN ('iPhone','Samsung')
              AND TD2.account_id = TD1.account_id
         );

答案 2 :(得分:0)

执行GROUP BY。在case子句中使用HAVING表达式来验证条件。

select account_id  
from tablename
group by account_id  
having count(case when model = 'iPhone' then 1 end) = count(*)   -- #1 Only iPhones
    or count(case when model = 'Samsung' then 1 end) = count(*)  -- #2 Only Samsung
    or count(distinct case when model in ('iPhone', 'Samsung') then model end) = 2 -- #3 both of them

说明:

1)-iPhone的数量与总数量相同,即仅iPhone。

2)-三星的数量与总数相同,即只有三星。

3)-不同的iPhone和三星的数量为2,即iPhone和三星。

相关问题