SQL Server:在IN和NOT IN中使用COUNT

时间:2016-09-05 12:01:45

标签: sql sql-server count

我有一个数据表如下:

file_id | action code
  1     |     10
  1     |     20
  2     |     10
  2     |     12
  3     |     10
  3     |     20
  4     |     10
  4     |     10
  4     |     20

输出结果为:

file_id | Warning
  1     |   0
  2     |   0  <- this should be 1 instead
  3     |   0
  4     |   1

第一个计数按预期工作,如果有任何action_code重复,则将警告设置为1,但如果action_code不能完全被10整除,我无法使其工作并显示警告

     @exported [int] = NULL,
 @bin_id [int] = NULL,
 @date_start [DateTime],
 @date_stop  [DateTime],
 @action_code  [int] = NULL,
 @action_description [varchar](43) = NULL

SELECT 
    dbo.Tf.file_id AS 'ID', 
    dbo.Tf.file_name AS 'NAME', 
    MAX(dbo.TFD.action_date) AS 'DATE', 
    MAX(dbo.TFD.file_length) AS 'SIZE', 
    dbo.Bins.name AS 'BIN',
    dbo.TFD.action_description, 

    CASE
    WHEN (COUNT(DISTINCT dbo.TFD.action_code) <> COUNT(dbo.TFD.action_code) )
    AND
    ((SELECT COUNT ( dbo.TFD.action_code ) FROM TFD WHERE action_code IN (10,20,30,40,50))  > 0
     AND
    (SELECT COUNT ( dbo.TFD.action_code ) FROM TFD WHERE action_code NOT IN (10,20,30,40,50))  > 0 ) THEN 1         
    ELSE 0 
    END AS 'Warning'            
FROM
(    SELECT
     dbo.Tf.file_id,
     MAX(dbo.TFD.action_code) AS 'action_code'

     FROM Tf 
     INNER JOIN TFD 
     ON Tf.file_id = TFD.file_id INNER JOIN Bins ON Tf.bin_id = Bins.bin_id

     WHERE
     (@bin_id IS NULL OR Tf.bin_id = @bin_id) 
      AND Tf.file_id IN 
                    (
                    SELECT H.file_id 
                    FROM Tf AS H INNER JOIN TFD AS D  ON H.file_id = D.file_id 
                    WHERE ((D.action_date >= @date_start AND D.action_date <= @date_stop) OR (H.file_date >= @date_start AND H.file_date <= @date_stop)) 
                    AND (H.bin_id = @bin_id OR @bin_id IS NULL) 
                    AND H.file_type = @exported 
                    AND ((@action_description IS NULL) OR (D.action_description LIKE @action_description + '%'))
                    )
      AND (@exported IS NULL OR Tf.file_type = @exported)

      GROUP BY dbo.Tf.file_id) AS TempSelect

 INNER JOIN Tf 
      ON Tf.file_id = TempSelect.file_id 
 INNER JOIN TFD 
      ON (TFD.file_id = TempSelect.file_id 
      AND TFD.action_code = TempSelect.action_code)
 INNER JOIN Bins ON Tf.bin_id = Bins.bin_id
 WHERE
   (
   (@action_code IS NULL ) OR (@action_code <> -1  AND TempSelect.action_code = @action_code) 
   OR (@action_code = -1 AND TempSelect.action_code NOT IN (10,20,30,40) )
   )
    GROUP BY
    dbo.Tf.file_id, 
    dbo.Tf.file_name, 
    dbo.Bins.name,
    dbo.Tf.bin_id,
    dbo.TFD.action_description
编辑:我添加了整个程序。我的主要目标是,如果满足以下条件,则将字段警告设置为1:

  1. 如果有任何action_code重复(因为它是文件4的情况)
  2. 如果每个文件的其他action_codes中都有一个不能被10整除的action_code(因为它是文件2的情况)

4 个答案:

答案 0 :(得分:1)

如果您的逻辑是:如果有重复项或者代码不能被10整除,请将标志设置为1,那么我建议:

dbo.Detail

请注意,我将d替换为表别名{{1}}。表别名使查询更易于编写,阅读和理解。

答案 1 :(得分:0)

希望这可以帮助你:

SELECT FILE_ID,
    MAX(CASE WHEN action_code % 10 != 0 THEN 1 END) not_divisible,
    CASE WHEN COUNT(*)!=COUNT(DISTINCT action_Code) THEN 1 END not_unique
FROM #test
GROUP BY FILE_ID

将所有内容放在一起,您可以使用:

SELECT file_id,
    CASE WHEN COUNT(*)!=COUNT(DISTINCT action_Code) THEN 1
         ELSE MAX(CASE WHEN action_code % 10 != 0 THEN 1 ELSE 0 END) END Warning
FROM #test
GROUP BY file_id

答案 2 :(得分:0)

尝试使用以下查询..

CREATE TABLE #t (FileID INT,ActionCode INT)

INSERT INTO #t
VALUES (1,10),(1,20),(2,10),(2,12),(3,10),(3,20),(4,10),(4,10),(4,20)

WITH cte_1
as (
SELECT *,COUNT(1) OVER(PARTITION BY FileID,ActionCode ORDER BY fileID,ActionCode) CNT
FROM #T)

SELECT  FileID,case WHEN SUM(ActionCode) %10 <>0 THEN 1 WHEN MAX(CNT)<>1 THEN 1 ELSE 0 END
FROM CTE_1
GROUP BY FileID

结果:

enter image description here

答案 3 :(得分:0)

感谢大家的回答,他们很有帮助,我修改了以下部分,现在它可以工作:

...
    dbo.TFD.action_description,
     CASE  
     WHEN (COUNT(DISTINCT dbo.TFD.action_code) <> COUNT(dbo.TFD.action_code)) OR err_ac > 0
     THEN 1 ELSE 0 END AS 'Warning'

FROM
( 
     SELECT
     dbo.Tf.file_id,
     MAX(dbo.TFD.action_code) AS 'action_code',
     CASE
     WHEN SUM(dbo.TFD.action_code) %10 <> 0 THEN 1 ELSE 0 END AS 'err_ac'
...